Разница между скобками [] и двойными скобками [[]] для доступа к элементам списка или фрейма данных

Вы распечатываете мусор, потому что recv не завершает нуль вашего буфера.

Важным разделом в приведенном ниже коде является:

int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;

send(client, ">> ", 3, 0);     // <<-- Nice to have.
send(client, buffer, num, 0);

buffer[num] = '\0';            // <<-- Really important bit!

if (buffer[num-1] == '\n')     // <<-- Nice to have.
    buffer[num-1] = '\0';      // <<-- Nice to have.

cout << buffer << endl;

, который будет надлежащим образом завершите свой буфер перед тем, как его распечатать, а также удалите завершающую новую строку, если она есть (и разрешите клиенту различать входные и эхо-строки).

Этот (полная программа) работает немного лучше:

using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>

#define BUFSIZE 1000
#define PORT 1234

int main() {
    char buffer[BUFSIZE];

    // define our address structure, stores our port
    // and our ip address, and the socket type, etc..
    struct sockaddr_in addrinfo;
    addrinfo.sin_family = AF_INET;
    addrinfo.sin_port = htons(PORT);
    addrinfo.sin_addr.s_addr = INADDR_ANY;

    // create our socket.
    int sock;
    if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0))  < 0) {
        cout << "Error in creating the socket.";
        return -1;
    }

    // bind our socket to the actual adress we want
    if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
        cout << "Error in binding.";
        return -1;
    }

    // open the socket up for listening
    if (listen(sock, 5) != 0) {
        cout << "Error in opening listener.";
        return -1;
    }

    char *msg = "Success! You are connected.\r\n";

    // continuously accept new connections.. but no multithreading.. yet
    while(1) {
        cout << "Waiting for connections...." << endl;

        struct sockaddr_in client_addr;
        socklen_t sin_size = sizeof(client_addr);

        if(int client =
            accept(sock, (struct sockaddr*)&client_addr, &sin_size))
        {
            cout << "Recieved new connection from "
                << inet_ntoa(client_addr.sin_addr) << endl;
            send(client, msg, strlen(msg), 0);
            while(1) {
                int num = recv(client,buffer,BUFSIZE,0);
                if (num < 1) break;
                send(client, ">> ", 3, 0);
                send(client, buffer, num, 0);

                buffer[num] = '\0';
                if (buffer[num-1] == '\n')
                    buffer[num-1] = '\0';
                cout << buffer << endl;
                strcpy(buffer, "");
            }
        } else {
            cout << "Error in accepting new connection." << endl;
        }
    }
    close(sock);
    return 0;
}

На стороне клиента:

$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.

и на стороне сервера:

$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....
472
задан Jaap 26 April 2019 в 10:04
поделиться

4 ответа

Определение языка R удобно для ответов на следующие типы вопросов:

R имеет три основных оператора индексации, синтаксис которых показан в следующих примерах.

  x [i]
 х [i, j]
 х [[i]]
 х [[i, j]]
 x $ a
 x $ "а"

Для векторов и матриц формы [ используются редко, хотя они имеют некоторые незначительные семантические отличия от формы [) (например, она удаляет все атрибуты name или dimnames, и что частичное соответствие используется для символьных индексов). При индексировании многомерных структур с одним индексом x [[i]] или x [i] вернет i -й последовательный элемент ] х .

Для списков обычно используется [[] для выбора любого отдельного элемента, тогда как [ возвращает список выбранных элементов.

Форма [[] позволяет выбрать только один элемент с использованием целочисленных или символьных индексов, тогда как [ позволяет индексировать по векторам. Однако обратите внимание, что для списка индекс может быть вектором, и каждый элемент вектора применяется по очереди к списку, выбранному компоненту, выбранному компоненту этого компонента и так далее. В результате по-прежнему остается единственный элемент.

308
ответ дан 22 November 2019 в 22:41
поделиться

Двойные скобки обращаются к элементу списка , а одиночные скобки возвращают список с единственным элементом.

lst <- list('one','two','three')

a <- lst[1]
class(a)
## returns "list"

a <- lst[[1]]
class(a)
## returns "character"
106
ответ дан 22 November 2019 в 22:41
поделиться

[] извлекает список, [[]] извлекает элементы в списке

alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))

str(alist[[1]])
 chr [1:3] "a" "b" "c"

str(alist[1])
List of 1
 $ : chr [1:3] "a" "b" "c"

str(alist[[1]][1])
 chr "a"
46
ответ дан 22 November 2019 в 22:41
поделиться

Существенные различия между двумя методами заключаются в классе объектов, которые они возвращают при использовании для извлечения, и в том, могут ли они принимать диапазон значений или только одно значение во время присвоения.

Рассмотрим случай извлечения данных в следующем списке:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

Допустим, мы хотели бы извлечь значение, хранящееся в bool, из foo и использовать его внутри оператора if () . Это продемонстрирует различия между возвращаемыми значениями [] и [[]] , когда они используются для извлечения данных. Метод [] возвращает объекты списка классов (или data. frame, если foo был data.frame), а метод [[]] возвращает объекты, класс которых определяется типом их значений.

Таким образом, использование метода [] приводит к следующему:

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical

class( foo[ 'bool' ] )
[1] "list"

Это потому, что метод [] возвратил список, а список не является допустимым объектом для передачи непосредственно в if () заявление. В этом случае нам нужно использовать [[]] , потому что он вернет "пустой" объект, хранящийся в 'bool', который будет иметь соответствующий класс:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"

class( foo[[ 'bool' ]] )
[1] "logical"

Второе отличие состоит в том, что [] может использоваться для доступа к диапазону слотов в списке или столбцам в кадре данных, в то время как оператор [[]] ограничен доступом к одиночному слот или столбец. Рассмотрим случай присвоения значений с использованием второго списка, bar () :

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

Допустим, мы хотим перезаписать последние два слота foo данными, содержащимися в bar. Если мы попытаемся использовать оператор [[]] , произойдет следующее:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

Это потому, что [[]] ограничен доступом к одному элементу. Нам нужно использовать []:

foo[ 2:3 ] <- bar
print( foo )

$str
[1] "R"

$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0

$bool
[1] -0.6291121

Обратите внимание, что, хотя присвоение было успешным, слоты в foo сохранили свои оригинальные имена.

165
ответ дан 22 November 2019 в 22:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: