如何将一个字符串中的多个单词分配给各个独立变量?

时间:2017-04-06 01:20:48

标签: c

HELP。 PLS。我是C编程&我正在尝试将字符串中的单词分配给单个变量。有任何想法吗?可以使用什么功能来做到这一点?

例如:

{
    printf("Input Full Name: ");
    string c = Get_String();

    // User inputs "Mack Moore";
    // then to achieve the below:

    string a = "Mack";
    string b = "Moore";
}

我该怎么办?打破字符串&将每个单词分配给单独的变量?

或者:如果那是不可能的话。我真正想要的是:

{
    printf("%c%c\n", a[0], b[0]);
}

给予:

~ MM

请帮助

2 个答案:

答案 0 :(得分:0)

在C中,字符串被视为字符数组,因此

"Mack Moore"

将是

{'M','a','c',k',' ','M','o','o','r','e'}

您正在寻找的内容称为标记化。它根据分隔符拆分字符数组。它本质上用空终止符替换分隔符(在您的情况下为空格),并吐出指向分割字符串开头的指针。然后用NULL替换输入字符串,它将继续输出下一个分隔部分,直到到达结尾。该代码不包括所有需要的声明等。仅用作指南:

#include string.h

/*get your input string here*/

a = strtok(input, ' ');
b = strtok(NULL, ' ');

printf("%c%c\n", a[0], b[0]);

如果你在字符串中有无限量的单词,你可以在循环中坚持这个strtok调用

答案 1 :(得分:0)

如果目标是将包含两个单词的字符串分成两个字符串,那么解决方案很简单。您可以使用fgets()获取一行输入,并使用sscanf()将两个字符串存储在适当的变量中。请注意,从buffer接收输入的fgets()的大小非常大,以减少缓冲区溢出的可能性。另请注意,使用%s转换说明符时,应始终指定最大宽度,以避免缓冲区溢出。您应该始终检查scanf()函数系列返回的值;这里返回值用于在没有给出足够信息的情况下提示用户再次输入输入。

#include <stdio.h>

#define BUFF_SZ  1000
#define NAME_SZ  50

int main(void)
{
    char firstname[NAME_SZ];
    char lastname[NAME_SZ];

    char buffer[1000];
    printf("Input Full Name: ");
    fgets(buffer, sizeof buffer, stdin);

    while (sscanf(buffer, "%49s %49s",
                  firstname, lastname) != 2) {
        printf("Please enter a first and a last name: ");
        fgets(buffer, sizeof buffer, stdin);
    }

    printf("Hello, %s %s\n", firstname, lastname);

    return 0;
}

如果存在第一个,中间名和姓氏的可能性,则可以修改此代码以相应地执行操作。此处,sscanf()返回的值存储在res中。如果不是23,系统会提示用户再次输入。如果返回的值为2,则未输入姓氏,因此middlename中存储的字符串将复制到lastnamemiddlename将更改为空字符串。< / p>

请注意,此代码稍微复杂一些,现在string.h函数原型已包含strcpy()头文件。

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

#define BUFF_SZ  1000
#define NAME_SZ  50

int main(void)
{
    char firstname[NAME_SZ];
    char middlename[NAME_SZ];
    char lastname[NAME_SZ];

    char buffer[1000];
    printf("Input Full Name: ");
    fgets(buffer, sizeof buffer, stdin);

    int res;
    while ((res = sscanf(buffer, "%49s %49s %49s",
                         firstname, middlename, lastname)) != 2 && res != 3) {
        printf("Please enter at least first and last name: ");
        fgets(buffer, sizeof buffer, stdin);
    }

    if (res == 2) {
        strcpy(lastname, middlename);
        middlename[0] = '\0';
    }

    printf("Hello, %s ", firstname);
    if (middlename[0] != '\0') {
        printf("%s ", middlename);
    }
    printf("%s\n", lastname);

    return 0;
}

对于更多不确定的要求,可能需要strtok()来将输入字符串分解为标记。这里声明了一个指向char的指针数组。这需要足够大以容纳指向字符串中所有单词的指针,并且可能需要在某些情况下动态分配。

此处,strdup()用于创建strtok()返回的令牌的副本。内存由strdup()函数分配,调用者有责任在程序终止前释放它。请注意strdup()不在C标准库中,但它是POSIX,并且非常常见。该程序的第一行是一个功能测试宏,可能需要它才能使用此功能。另请注意,stdlib.h函数原型已包含free()头文件。

在所有这些示例中,还应检查从fgets()返回的值,并在最后一个示例中检查它。如果fgets()中出现错误,则会打印一条消息并退出程序。

#define _POSIX_C_SOURCE 200809L

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

#define BUFF_SZ    1000
#define MAX_WORDS  1000

int main(void)
{
    char buffer[1000];
    printf("Enter a string of words:\n");
    if (fgets(buffer, sizeof buffer, stdin) == NULL) {
        fprintf(stderr, "Error in fgets()\n");
        exit(EXIT_FAILURE);
    }

    char *token;
    char *words[MAX_WORDS];
    char *delims = " \t\r\n";
    size_t counter = 0;

    token = strtok(buffer, delims);
    while (token != NULL) {
        words[counter] = strdup(token);
        ++counter;
        token = strtok(NULL, delims);
    }

    for (size_t i = 0; i < counter; i++) {
        puts(words[i]);
    }

    /* Free allocated memory */
    for (size_t i = 0; i < counter; i++) {
        free(words[i]);
    }

    return 0;
}

更新

OP已经提到在评论中对fgets()缺乏了解,而Get_String()是用于获取输入线的函数。 Get_String()不是标准的C函数。从上下文中,我怀疑这个函数返回一个指向char的指针,并且函数为字符串分配内存。如果是这种情况,则需要在程序终止之前释放这些分配。

修改上述示例以使用GetString()应该相对简单,但我强烈建议您了解fgets()。如果stringchar *的别名,我怀疑,那么你不能简单地声明string firstname;,因为这不会为字符串分配内存。因此,您需要声明数组以保存名字和姓氏。我不保证这段代码,因为我无法访问函数GetString(),但第一个示例可能会被重写为:

#include <stdio.h>

#define NAME_SZ  50

int main(void)
{
    char firstname[NAME_SZ];
    char lastname[NAME_SZ];

    string buffer;
    printf("Input Full Name: ");
    buffer = GetString();

    while (sscanf(buffer, "%49s %49s",
                  firstname, lastname) != 2) {
        printf("Please enter a first and a last name: ");
        free(buffer);
        buffer = GetString();
    }

    printf("Hello, %s %s\n", firstname, lastname);

    free(buffer);
    return 0;
}

请注意,buffer在程序结束前被释放。另请注意,如果输入不正确并且需要更多输入,则会释放buffer。在这种情况下,调用GetString()buffer分配新内存,因此必须首先释放旧内存。这种增加的复杂性是避免像string这样的类型别名的一个原因。使用string代替char *的设备被一些人认为对教学有用,但我不同意;它实际上使用了不必要的复杂和混乱的字符串。最好学习实际编写代码的方式。