2010-07-18 2 views
3

У меня есть обугленных БУФ [х], INT с и недействительными * Данные.С - читать строки из буфера определенного размера

Я хочу написать строку размером s в данных из Buf.

Как это сделать?

Заранее благодарен.

+2

Является ли 'buf' строкой с нулевым разделителем или ее размер определяется' s'? Вы пытаетесь скопировать только часть строки? Что такое 'x'? Строка, скопированная в 'data', должна быть ограничена нулями? что ты уже испробовал? – zvone

+0

Обратите внимание, что кафе указал на несколько ошибок в моем ответе. Я отредактировал свой ответ, чтобы учесть его комментарии. – Gilles

ответ

4

Предполагая, что

  • «string» означает строку с нулевым символом, как это обычно подразумевается в C;
  • Вы еще не выделили память в data;
  • вы уже знаете, что S = < х

Прежде всего, необходимо выделить память в data. Не забудьте комнату для байт 0 в конце строки.

data = malloc(s+1); 
if (data == NULL) { 
    ... /*out-of-memory handler*/ 
} 

Предполагая malloc успешно, теперь вы можете скопировать байты.

EDIT:

Лучшая функция для работы, как было отмечено кафе, является strncat. (Это полностью портативный, являющийся частью C89.) Он добавляет к строке назначения, так организовать для назначения, чтобы быть пустой строкой заранее:

*(char*)data = 0; 
strncat(data, buf, s); 

Другие низшие возможности, хранятся здесь, чтобы служить в качестве примеров связанных функций:

  • Если вы есть strlcpy (который не является стандартным C, но часто встречается на современных системах Unix, существуют реализации публичных доменов, плавающие вокруг):

    strlcpy(data, buf, s+1); 
    
  • Если вы знаете, что есть по крайней мере s символов в исходной строке, вы можете использовать memcpy:

    memcpy(data, buf, s); 
    

    ((символ *) данные) [s + 1] = 0;

  • В противном случае вы можете вычислить длину строки исходного первого:

    size_t bytes_to_copy = strlen(buf); 
    if (bytes_to_copy > s) bytes_to_copy = s; 
    memcpy(data, buf, bytes_to_copy); 
    ((char*)data)[s+1] = 0; 
    
  • Или вы можете использовать strncpy, хотя это неэффективно, если фактическая длина строки источника намного меньше, чем s:

    strncpy(data, buf, s); 
    ((char*)data)[s+1] = 0; 
    
+2

В ваших реализациях memcpy() есть ошибки - они оба неправильно помещают nul-terminator, и они пытаются разыменовать 'void *', что вы не можете сделать. Первый должен использовать данные '((char *)) [s] = 0', а второй должен использовать данные' ((char *)) [bytes_to_copy] = 0; '. Для последнего вместо 'strncpy()' вы можете использовать 'strncat()': '((char *) data) [0] = 0; strncat (data, buf, s); ' – caf

+0

@caf: вы правы по обоим пунктам. К сожалению, мой ответ был принят, поэтому я отредактировал его, а не удалял, потому что я не хочу оставлять неправильный ответ слишком заметным. Но если вы напишете ответ strncat, я выберу его. – Gilles

2
memcpy(data, buf, s); 

Это предполагает, что у вас достаточно места в данных (и в buf).

В зависимости от того, что вы делаете (вы не говорите, но вы говорите, что копируете строки), вы можете захотеть добавить нуль в конце вашей новой скопированной строки, если вы не скопировали нулевой уже в buff, и вы собираетесь использовать данные в функции, которая ожидает строки.

3

Если data не выделяется:

char buf[] = "mybuffer"; 
void *data = malloc(strlen(buf)+1); 
strcpy((char*)data,buf); 

На самом деле, если данные действительно должны быть определены также можно сделать

char buf[] = "mybuffer"; 
void *data= (void*)strdup(buf); 
+2

Вы должны 'malloc (strlen (buf) +1)' – sje397

+0

Не являются ли строковые литералы нулевыми терминами? – Jack

+0

Да, и здесь 'buf' имеет нулевое завершение, хотя [это не строковый литерал] (http://c-faq.com/aryptr/aryptr2.html). Но 'strlen (buf)' не включает байт терминатора в свой счет. – Gilles

2
int n = MIN((x - 1), s); 
char *bp = buf; 
char *dp = (char *)data; 
while (n--) { 
    *bp++ = *dp++; 
} 
*dp = '\0';