2014-10-17 5 views
1

Я думаю, что этого фрагмента кода достаточно, чтобы понять, что я делаю. Я использую getline для чтения входных данных из текстового файла, который имеет строки, которые могут выглядеть примерно так: Кошка жирная/И любит петьКак работает memset в этом фрагменте кода?

От поиска в Интернете я смог заставить его работать, но я хотел бы лучше понять, ПОЧЕМУ он работает. Мой главный вопрос: как

memcpy(id, buffer, temp - buffer); 

линия работает. Я читал то, что делает memcpy(), но не понимает, как работает часть temp-buffer. Итак, из моего понимания я устанавливаю *temp в '/' в этой строке. Затем я копирую строку до тех пор, пока в нее не войдет '/'. Но как работает темп, который находится на отметке «/» за вычетом буфера (который является всей линией от getline), чтобы просто быть кошкой?

Надеюсь, это имело смысл.

#define MAX_SIZE 255 

char buffer[MAX_SIZE + 1] = { 0 }; 
cin.getline(buffer, MAX_SIZE); 

memset(id, 0, 256); 
memset(title, 0, 256); 

char* temp = strchr(buffer, '/'); 
memcpy(id, buffer, temp - buffer); 
temp++; 
strcpy(title, temp); 

Кроме того, если я могу удвоить провал, почему max_size быть определен на 255, но MAX_SIZE +-часто используются. Это связано с разделителем или пробелом в конце строки? Спасибо за помощь.

+0

Я не уверен, что ваше название - это то, что вы намеревались. Вызовы 'memset' в этом коде наиболее прямолинейны:« заполните эту область памяти на этом начальном адресе этим октетом для этого множества повторений ». Я думаю, что «temp-buffer» в вызове ** 'memcpy' ** будет более интересным (и его вычислением * указателя-разницы *, стоит googling). – WhozCraig

ответ

1

Здесь вы подсчитаете позицию первого / в буфере.

char* temp = strchr(buffer, '/'); 

Теперь temp указывает на / в буфере. Если вы хотите скопировать эту часть буфера, ее достаточно, чтобы получить указатель на начало и длину строки. Таким образом, temp - buffer оценивает длину.

================================= 
The cat is fat/And likes to sing 
================================= 
^   ^
buffer  temp 

| length | = temp - buffer 

Конца нуль строки детерминированной по \0 (или просто 0). Поэтому, если вам нужно хранить N символов, вам нужно выделить размер буфера N + 1.

1
MAX_SIZE+1 is reserving space for the null terminator at the end of the string ('\0') 

memcpy(id, buffer, temp - buffer) 

Это копирование (temp-buffer) байтов из буфера в id. Поскольку strchr находит символ «/» на входе, temp указывает внутри буфера (при условии, что он найден). Так, например, предположим, точки буфера в ячейку памяти:

буфера = 0x781230001

и третий байт является '/', после того, как strchr, у вас есть

температура = 0x781230003

темп - буфер поэтому равен 2.

ОДНАКО: Если «/» не найден, то temp не будет работать, и код будет аварийно завершен. Вы должны проверить результат strchr перед выполнением арифметики указателя.

2

По-моему, это просто плохой код.:) Я хотел бы написать это как

const size_t MAX_SIZE = 256 

char buffer[MAX_SIZE] = {}; 

std::cin.getline(buffer, MAX_SIZE); 

id[0] = '\0'; 
title[0] = '\0'; 

if (char* temp = strchr(buffer, '/')) 
{ 
    std::memcpy(id, buffer, temp - buffer); 
    id[temp - buffer] = '\0'; 
    std::strcpy(title, temp + 1); 
} 
else 
{ 
    std::strcpy(id, buffer); 
} 

Что касается memcpy в этом заявлении

memcpy(id, buffer, temp - buffer); 

затем он копирует темп - буфер байтов из буфера в ид. Поскольку идентификатор ранее был установлен в ноль, то после memcpy он будет содержать строку с завершающим нулем.

2

Ты вопрос касается стрелочной разницы расчета, часть семейства арифметических операций, которые выполняются в указателе арифметической.

Большинство новичков не слишком беспокоятся о том, как работает указатель. Учитывая это:

char buffer[256]; 
char *p = buffer + 10; 

это, как правило, ясно, что p указывает на 10-й слот в buffer массив символов. Но вы должны помнить, что указатель тип важен. Та же конструкция, вы видите выше, также работает для более сложных типов данных:

struct Something 
{ 
    char name[128]; 
    int ident; 
    int supervisor; 
} people[64]; 

struct Something *p = people+10; // NOTE: same line, different types 

Так же, как и раньше, p указывает на десятый элемент в массиве, но обратите внимание на арифметику; размер базового типа используется для вычисления соответствующего смещения памяти. Вам не нужно делать это самостоятельно. Здесь нет sizeof.

Так почему вас это волнует? Так как обычная математика, указатель по математике имеет определенные свойства, один из них следующее:

char buffer[256]; 
char *p = buffer+10; // p addresses the 10th slot in the array 
size_t len = p-buffer // len is the typed-difference between p and buffer. 

В этом случае len будет 10, так же, как смещение p. Итак, как это относится к вашему вопросу? Ну ...

char* temp = strchr(buffer, '/'); 
memcpy(id, buffer, temp - buffer); 

ужасной природы этого кода в стороне (если нет в массиве buffer результат является temp быть NULL не '/', и последующий тетсру будет все-но-гарантия массивное выдаёт ошибку сегментации). Этот код находит местоположение в строке, где находится '/'. Как только это имеет место, в вычислении temp - buffer используется арифметика указателя (в частности, различие указателей) для вычисления расстояния между адресом в temp и адресом в качестве базы массива. Результатом является количество элементов , не считая самого коса. Поэтому этот код копирует до, но не включая обнаруженную косую черту, в буфер id. Остальная часть буфера id сохраняет все значения 0, заполненные memset, и поэтому строка прекращается (что намного больше, чем вам нужно, btw).

После этой линии, остальные:

temp++; 
strcpy(title, temp); 

пост-приращение указателя температуры, который говорит, что «перейти к следующему элементу в массиве». Затем strcpy копирует оставшиеся символы нулевой строки buffer в title.Стоит отметить, это может быть просто:

strcpy(title, ++temp); 

и также:

strcpy(title, temp+1); 

, который сохраняет temp на '/' позиции. Во всем вышеизложенном результат в title будет таким же: все символы после косая черта, но не включая его.

Надеюсь, это объяснит, что происходит. Удачи.

+0

Спасибо, это действительно помогло! – SuperCow

Смежные вопросы