如何在 C 中将字符串分配给结构变量?

How to assign a string to struct variable in C?

提问人:sameed hussain 提问时间:2/25/2022 最后编辑:Vlad from Moscowsameed hussain 更新时间:2/25/2022 访问量:1504

问:

我无法弄清楚如何仅使用 <stdio.h> 头文件将字符串分配给结构变量。

以下代码给了我一个错误,我无法修复它。

#include <stdio.h>
 struct Student
{
    char name[50];
};
int main()
{
   struct Student s1;
   printf("Enter studen's name:\n");
   scanf("%s",s1.name);
   printf("Name : \n",s1.name);
   s1.name={"Hussain"};
   printf("Name : \n",s1.name);
}

它在编译时给出以下错误:

test.c: In function 'main':
test.c:12:12: error: expected expression before '{' token
    s1.name={"Hussain"};
            ^

我尝试以以下方式初始化它:

但这也不起作用。
我可以通过使用指针来避免这种情况,如下所示:
s1.name="Hussain";

#include <stdio.h>
 struct Student
{
    char *name;
};
int main()
{
   struct Student s1;
   printf("Enter studen's name:\n");
   scanf("%s",s1.name);
   printf("Name : %s\n",s1.name);
   s1.name="Hussain";
   printf("Name : %s\n",s1.name);
}

这段代码工作得很好,没有错误。
但是我想知道我到底在数组上做错了什么,这使我的代码无法正常工作。

数组 初始化 C-strings 赋值运算符

评论


答:

4赞 dbush 2/25/2022 #1

char 数组(以及一般的数组)不能直接赋值,只能初始化。若要将字符串写入 char 数组,请使用 。strcpy

strcpy(s1.name, "Hussain");

成员是指针的后一种代码适用于赋值,因为指针被分配了字符串常量开头的起始地址。另请注意,在这种情况下您不能(至少现在还不能)使用,因为它不会指向任何地方。您首先需要使用 分配内存,或者使用 同时执行这两个步骤。同样出于这个原因,在分配内存之前还不能使用。namestrcpys1.namemallocstrdupscanf

如果你不被允许使用 string.h 中的函数,那么你需要一次将一个字符写入数组,然后在末尾写一个终止的 null 字节。

评论

0赞 sameed hussain 2/25/2022
哦。。所以基本上我们必须这样做。
1赞 Zakk 2/25/2022
“仅使用<stdio.h>......”
3赞 Vlad from Moscow 2/25/2022 #2

数组没有赋值运算符。所以这些赋值语句

s1.name = { "Hussain" };
s1.name = "Hussain";

是无效的。

您可以使用标准的 C 字符串函数将字符串文本的元素复制到数组中,例如strcpys1.name

#include <string.h>

//...

strcpy( s1.name, "Hussain" );

如果你不能使用标准的字符串函数,那么你需要编写一个循环,例如

const char *p = "Hussain";

for ( char *t = s1.name; ( *t++ = *p++ ) != '\0'; );

for ( char *t = s1.name, *p = "Hussain"; ( *t++ = *p++ ) != '\0'; );

请注意,您的程序具有未定义的行为。指针未初始化,并且不指向数组类型的有效对象。因此,此代码片段中的调用调用了未定义的行为。s1.namescanf

struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);

评论

0赞 sameed hussain 2/25/2022
非常感谢你把事情说得很清楚!
1赞 Zakk 2/25/2022 #3

如果你不能使用 ,那么你必须实现你自己的版本:<string.h>strcpy()

void copystring(char *dest, const char *src)
{
    const char *p = src;
    while (*p) {
        *dest = *p;
        p++;
        dest++;
    }
    *dest = '\0'; // Null-terminate string (as pointed by @Ted)
}

确保有足够的空间来容纳 .destsrc

此外,请避免在代码中使用。用作替代方法。scanf()fgets()

编辑:正如 Jabberwocky 所指出的,叶子在字符串中读取。但是由于不允许使用,因此您必须实现自己的函数以将其替换为 null 终止符:fgets()\n<string.h>

int findchar(const char *str, char c)
{
    int pos;
    for (pos = 0; str[pos]; ++pos)
        if (str[pos] == c)
            return pos;
    
    return -1;
}

您可以像以下方式使用它:

char str[100];
if (!fgets(str, sizeof str, stdin)) {
    // fgets() failed. Do something.
} else {
    int nwln = findchar(str, '\n');
    if (nwln == -1) {
        // You probably entered more than 100 characters
        // because \n couldn't be found.
    } else {
        str[nwln] = '\0';
    }
}

评论

0赞 Jabberwocky 2/25/2022
然而,它也有自己的问题。它在字符串的末尾留下了一个可能必须处理的字符串。阅读: stackoverflow.com/questions/2693776/...fgets\n
0赞 Ted Lyngmo 2/25/2022
这看起来不会 null 终止 。您可以在循环后添加 - 或者在循环中复制 null 终止符。这是最多复制计数字符的替代方法。dest*dest = '\0';
0赞 Zakk 2/25/2022
@Jabberwocky我知道。我只是跳过了这一点,以保持答案简短。无论如何,我已经更新了我的答案。谢谢。
0赞 Zakk 2/25/2022
@TedLyngmo我已经回答了。谢谢。
0赞 Ted Lyngmo 2/25/2022
@Zakk fgets 在 ,而不是 .<stdio.h><string.h>