2010-12-19 1 views
0

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

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 достаточно хорошо, но может ли кто-нибудь объяснить мне, что происходит?

+0

Вы хотите, конечно, избавиться от этого malloc cast! http://c-faq.com/malloc/mallocnocast.html – user502515

ответ

5

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

strncpy не ставит нулевой ограничитель на строку для вас. Если вам нужна 2-символьная строка, вам нужно выделить место для трех символов и установить окончательное значение 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; 
// ... 

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

+0

спасибо и спасибо другим плакатам. Теперь я понимаю, что происходит, и мне удалось исправить мой код. очень благодарен! – Andrew

+0

без проблем ..... – sje397

2

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

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

Вы печатаете строки, которые не имеют нулевой последовательности. Для того, чтобы исправить эту DECLARE 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'; 
+0

Это не достаточно. Вы также должны поместить этот нулевой ограничитель после копирования. –

+1

Функция strncpy() всегда записывает «n» байты в пункт назначения, как и memcpy(). Единственная разница между strncpy() и memcpy() заключается в том, что байты, следующие за первым нулевым байтом, будут записываться как ноль, а не копироваться из источника. – supercat

1

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

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

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

+0

_пребывание s1_ всегда остается неизменным в моем опыте (MinGW). Может быть, заполнено с \ 0 characters_ в других средах. – Salvador