strncpy вопрос (язык C) - PullRequest
       5

strncpy вопрос (язык C)

0 голосов
/ 19 декабря 2010

У меня проблемы с strncpy. Я пытаюсь разбить строку из 8 символов на две (первые 6 символов в одной подстроке, а затем оставшиеся 2 символа в другой). Чтобы проиллюстрировать особую сложность, я упростил свой код до следующего:

include stdio.h
include stdlib.h
include string.h

define MAXSIZE 100

struct word {  
   char string[8];  
   char sub1[2];  
   char sub2[6];  
};

typedef struct word Word;

int main(void)  
{  
   Word* p;  
   p=(Word*)malloc(MAXSIZE*sizeof(Word));  
   if (p==NULL) {  
      fprintf(stderr,"not enough memory");  
      return 0;  
   }  
   printf("Enter an 8-character string: \n");  
   scanf("%s",p->string);  

   strncpy(p->sub2,p->string,6);  
   strncpy(p->sub1,p->string,2);  
   printf("string=%s\n",p->string);  
   printf("sub1=%s\n",p->sub1);  
   printf("sub2=%s\n",p->sub2);  

   free(p);  

   return 0;  
}

У пользователя запрашивается ввод. Предположим, они вводят «12345678». Тогда результат программы:

string=1234567812123456  
sub1=12123456  
sub2=123456

Результат, который я ожидаю, будет следующим:

string=12345678  
sub1=12  
sub2=123456

Я не понимаю, как strncpy, кажется, добавляет числа в строку ... Очевидно, я недостаточно хорошо понимаю strncpy, но кто-нибудь может мне объяснить, что происходит?

Ответы [ 3 ]

6 голосов
/ 19 декабря 2010

Строки C должны заканчиваться нулевым символом (0).

strncpy не ставит для вас нулевой терминатор строки.Если вам нужна двухсимвольная строка, вам нужно выделить место для трех символов и установить для последнего значение null.

Попробуйте:

struct word {
char string[9];
char sub1[3];
char sub2[7];
};

// ...
strncpy(p->sub2,p->string,6);
p->sub2[6] = 0;
strncpy(p->sub1,p->string,2);
p->sub1[2] = 0;
// ...

Обратите внимание, что если пользователь вводитбольше персонажей, чем вы выделили, у вас будут проблемы.

2 голосов
/ 19 декабря 2010

Вы можете найти эту часть документации strncpy полезной:

Функция strncpy () аналогична, за исключением того, что не более n байтов src копируются. Предупреждение: если среди первых n байтов нет нулевого байта для src строка, помещенная в dest, не будет иметь нулевое окончание.

Вы печатаете строки, которые не заканчиваются нулем. Чтобы исправить это, объявите sub1 и sub2 с дополнительным символом для терминатора:

char sub1[3];
char sub2[7];

И затем нулевое завершение после копирования:

strncpy(p->sub2,p->string,6);  
p->sub2[6] = '\0';
strncpy(p->sub1,p->string,2); 
p->sub1[2] = '\0';
1 голос
/ 19 декабря 2010

Функция strncpy () копирует не более n символов из s2 в s1. Если s2 меньше n символов, остаток от s1 заполняется с символами `\ 0 '. В противном случае s1 не завершается.

Таким образом, если ваша строка длиннее, строки не заканчиваются нулем. Когда вы печатаете их, prinf печатает скопированные символы, но затем продолжает печатать все, что есть, пока не достигнет NUL

Althoug scanf завершает NUL своей строкой, у вас недостаточно места. String в вашей структуре должно быть длиной 9 символов - 8 для символов (12345678) и еще один для NUL. Прямо сейчас NUL входит в первый символ str1 - который затем перезаписывается с помощью strncpy

...