Завершение строки в C- разница между хранением и сопоставлением - PullRequest
1 голос
/ 09 января 2012

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

I always thought that in C, strings was terminated by '\0' 

это один символ. (поэтому мы использовали одинарные кавычки)

Кроме того, мы можем сделать что-то вроде,

while ( a[i]!='\0' )
do blah blah


which suggests that '\0'

является одним символом и в идеале должен храниться в одной позиции.

Но когда я объявляю массив следующим образом:

char a[3];

и когда я пытаюсь выразить какое-то значение, скажите «привет».

Тогда

printing a[0] gives "h"
printing a[1] gives empty space  
printing a[2] gives 0

, что наводит на мысль, что \ был сохранен в позиции 1, а '0' - в позиции 2. и вся вещь '\ 0' не была сохранена вместе, несмотря на то, что мы использовали ее как один символ.

Почему это так? Кто-нибудь может пролить некоторую ясность на то же самое?

Спасибо!

РЕДАКТИРОВАТЬ:

#include <stdio.h>
void main()
{
int i=0;
char a[2];
fgets(a,sizeof(a),stdin); // Here I input "Hi".



while(a[i]!='\0')
    {
    printf("%c",a[i]);
    fflush(stdin);
    i=i+1;
    }
}

Ответы [ 5 ]

3 голосов
/ 09 января 2012

fgets принимает размер буфера в качестве второго аргумента и считывает, что минус один символов, а затем делает последний символ \0. Поскольку ваш массив имеет размер 2 (что, кстати, слишком мало для строки hi), fgets читает один символ и делает последний символ \0, поэтому у вас есть массив, который содержит h\0.

Чтобы все заработало, сделайте размер вашего массива 3; один для h, один для i и один для \0:

#include <stdio.h>

void main() {
    int i = 0;
    char a[3];
    fgets(a, sizeof(a), stdin); // Here I input "Hi".

    while(a[i] != '\0') {
        printf("%c",a[i]);
        fflush(stdin);
        i=i+1;
    }
}
2 голосов
/ 09 января 2012

Строки не заканчиваются символами \ и 0, скорее они заканчиваются значением NULL (символ 0), которое может быть представлено через escape-последовательность \0 - аналогично возврату каретки может быть представлен как \n.

1 голос
/ 09 января 2012
char a[2];
fgets(a,sizeof(a),stdin); // Here I input "Hi".

Второй аргумент fgets предназначен для получения общей длины буфера, как вы это сделали; но буфера 2 char большой достаточно только для 1 "полезного" символа и нулевого терминатора, поэтому fgets просто хранит H и сразу записывает '\0' (fgets гарантирует завершение строки, поэтому он будет всегда предпочитайте завершать строку вместо того, чтобы вводить другой «реальный символ», но не заканчивать строку).

После fgets ваш буфер будет выглядеть в памяти следующим образом:

+---+---+
| H |\0 |
+---+---+

Фактически, ваша программа на самом деле будет записывать только H. Если вы хотите увидеть «фактические числа», хранящиеся в каждом символе, вы можете сделать:

printf("%d %d", a[0], a[1]);

и вы получите 72 0 (где 72 - это H, а 0 - '\0').

( см. Пример )

0 голосов
/ 09 января 2012

'\ 0' - это escape-символ .

Чтобы скопировать "hi" в char a[3], все, что вам нужно сделать, это вызвать библиотечную функцию strcpy() следующим образом.

strcpy(a,"hi");

И, strcpy() может выглядеть так!

// array version
char * strcpy1(char to[], char from[])
{
        int i=0;
        while(from[i]) {
                to[i] = from[i];
                i++;
        }       
        to[i] = '\0';
        return to;
}

// pointer version
char * strcpy2(char *to, char *from)
{
        char *t = to;
        while (*to++ = *from++);
        return t;
}

Надеюсь, это поможет!

0 голосов
/ 09 января 2012

Вам определенно не хватает какого-то кода здесь. Как вы положили «привет» в переменную? Я думаю, что вы могли бы назначить указатель вместо всей строки (которая по сути является массивом).

Вы не можете копировать строки, просто назначая их. Выполнение этого при инициализации (например, char test[] = "hello!";) является специальным исключением.

char text1[] = "test"; // works (string is copied at runtime)
char text2[5]; // so far empty / content not defined
text2 = "test"; // won't work (depending on  your compiler settings it's possible there's no error, but you won't copy/assign the string)

strcpy(text2, "test"); // works, but might be unsafe (buffer overrun); requires string.h

text2[0] = 't';
text2[1] = 'e';
text2[2] = 's';
text2[3] = 't';
text2[4] = '\0'; // works too, but not recommended for longer stuff (1-2 chars is most likely okay, depending on the usage)

Как уже упоминалось в некоторых других публикациях, ваша проблема заключается в том, что массив может принимать только строку длиной 1 (как я упоминал ниже, для строки, собирающей x символов, вам нужно x + 1 элементов массива (для хранения окончание '\0').

Строка "Hi!\0" (обратите внимание на явное завершение; просто чтобы показать вам) в памяти будет выглядеть следующим образом: 0x00 0x48 0x69 0x21 0x00 0x00 \ только в вашем написанном коде сообщает компилятору, что специальный символ будет следовать. \ не появится в окончательном коде программы. Прочтите руководство по строковым литералам и экранирующим символам, если вы хотите узнать больше об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...