将包含空格的句子扫描到C

时间:2016-04-15 09:41:44

标签: c

我不擅长使用C语言。这是我愚蠢的问题。现在我试图从用户那里获得输入,这些用户可能有空格。我需要做的是使用空格作为分隔符来拆分这句话,然后将每个片段放入char *数组。
例如:
假设我有char* result[10];,输入为:Good morning John。输出应该是result[0]="Good"; result[1]="morning"; result[2]="John";我已经尝试scanf("%[^\n]",input);gets(input);但是仍然很难处理C中的String。我也试过了strtok,但它似乎只用NULL替换了空格。因此结果将是GoodNULLmorningNULLJohn。显然这不是我想要的。请帮助我愚蠢的问题。谢谢。
修改
这是使用strtok时我不明白的地方。这是一个测试代码。 substr仍然显示Hello there。似乎subtok仅替换空格位置的null。因此,我无法在substr声明中使用if

int main()
{
    int i=0;
    char* substr;
    char str[] = "Hello there";
    substr = strtok(str," ");

    if(substr=="Hello"){
        printf("YES!!!!!!!!!!");
    }

    printf("%s\n",substr);

    for(i=0;i<11;i++){
        printf("%c", substr[i]);
    }

    printf("\n");
    system("pause");
    return 0; 
}

3 个答案:

答案 0 :(得分:3)

从不使用gets,在C99中已弃用并从C11中删除。

IMO scanf不是一个很好的功能,当你不知道前面的元素数量时,我建议fgets

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[128];
    char *ptr;

    fgets(str, sizeof str, stdin);
    /* Remove trailing newline */
    ptr = strchr(str, '\n');
    if (ptr != NULL) {
        *ptr = '\0';
    }
    /* Tokens */
    ptr = strtok(str, " ");
    while (ptr != NULL) {
        printf("%s\n", ptr);
        ptr = strtok(NULL, " ");
    }
    return 0;
}

答案 1 :(得分:1)

建议不要使用

gets,因为无法判断缓冲区的大小。 fgets在这里没问题,因为遇到第一个新行时它会停止读取。您可以使用strtok将所有已拆分的单词存储到字符串数组中,例如:

#include <stdio.h>
#include <string.h>

int main(void) {
    char s[256];
    char *result[10];

    fgets(s, sizeof(s), stdin);
    char *p = strtok(s, " \n");
    int cnt = 0;
    while (cnt < (sizeof result / sizeof result[0]) && p) {
        result[cnt++] = p;
        p = strtok(NULL, " \n");
    }
    for (int i = 0; i < cnt; i++)
        printf("%s\n", result[i]);
    return 0;
}

答案 2 :(得分:0)

由于大多数其他答案都没有涉及你要问的另一件事:

strtok将不会分配临时内存,并将使用您的给定字符串替换零终止的每个分隔符。这就是Good morning John成为GoodNULLmorningNULLJohn的原因。如果它不这样做,每个令牌将在其尾部打印整个字符串的其余部分,如:

result[0] = Good morning John
result[1] = morning John
result[2] = John

因此,如果您想保留原始输入和每个单词的char *数组,则需要2个缓冲区。除此之外别无他法。只要使用char *指针的结果数组,您还需要令牌缓冲区保留在作用域中,否则会指向无效的内存并导致未定义的行为。

所以这可能是一个解决方案:

int main()
{
    const unsigned int resultLength = 10;
    char* result[resultLength];
    memset(result, 0, sizeof result);   // we should also zero the result array to avoid access violations later on

    // Read the input from the console
    char input[256];
    fgets(input, sizeof input, stdin);

    // Get rid of the newline char
    input[strlen(input) - 1] = 0;

    // Copy the input string to another buffer for your tokens to work as expected
    char tokenBuffer[256];
    strcpy(tokenBuffer, input);

    // Setting of the pointers per word
    char* token = strtok(tokenBuffer, " ");
    for (unsigned int i = 0; token != NULL && i < resultLength; i++)
    {
        result[i] = token;
        token = strtok(NULL, " ");
    }

    // Print the result
    for (unsigned int i = 0; i < resultLength; i++)
    {
        printf("result[%d] = %s\n", i, result[i] != NULL ? result[i] : "NULL");
    }
    printf("The input is: %s\n", input);

    return 0;
}

打印:

result[0] = Good
result[1] = morning
result[2] = John
result[3] = NULL
result[4] = NULL
result[5] = NULL
result[6] = NULL
result[7] = NULL
result[8] = NULL
result[9] = NULL
The input is: Good morning John