【问题标题】:C - How to get string from user when using typedef?C - 使用 typedef 时如何从用户那里获取字符串?
【发布时间】:2017-11-16 19:33:35
【问题描述】:

我的代码中有以下 typedef:

typedef char * string;

我需要让用户输入一个字符串,这样我才能解析它并在以后使用其中的内容。如果我只是用这个定义声明一个字符串,它就可以工作,就像这样:

string bob = "My name is bob!;
printf("%s\n", bob);

在使用它时我应该使用什么来获取用户输入,scanf() 和 fgets() 当我尝试使用它们时,它们都给我 Segmentation fault (core dumped) 错误。

这是给学校的,这就是为什么我需要以这种方式使用 typedef。

【问题讨论】:

  • 问题不在于你的 typedef;你可以像写char *一样使用它。问题是目标:使用字符串文字初始化bob 时,它通常驻留在不可写内存中,因此存在段错误(从技术上讲,它是UB)。尝试用malloc()初始化它
  • 字符串文字在只读内存中。你不能改变它们。所以也不能在 scanf 中使用。使用char str[MAXSIZE]char *str =malloc(sizeof (char) *MAXSIZE)。尝试修改只读内存是未定义的行为。还有malloc,当你分配..检查返回值,也不要忘记free他们。在这种情况下,正如您所说typedef has problem...不,它没有。 typedef 应该用于您想要使用的复杂类型...这里因为typedef-ing char* 而失去可读性。 Segfaults-由程序试图读/写非法内存引起
  • 在C语言中typedef a pointer不是一个好主意。
  • @coderredoc 详细信息:“字符串文字在只读内存中”几乎是正确的,并且对学习者来说是一个有用的公理。然而,C 中没有只读内存要求。写入 string literal 可能“有效”,但可能不会。毕竟是UB。
  • 非常感谢大家的回答,他们帮了大忙!

标签: c pointers scanf fgets


【解决方案1】:

您可以使用typedefpointer variable,但在使用或访问typedefed pointer variable 时必须小心,因为通常您不会在declarationdefinition 中看到* 符号,而definition 可能在其他地方,而您可以视为正常变量。

如果您想从运行时或文件中获取指针变量的输入,您应该首先分配内存。

int main()
    {
            typedef char * string;// now string also a char pointer
            string bob;// bob is pointer variable
            printf("enter the string\n");
            scanf("%s",bob);//bob is uninitialized pointer .. u can't put any data
            printf("%s\n", bob);
          //once job is done free dynamically allocated memory using free function 
    }

以上代码会导致分段错误,所以先动态分配内存。

        string bob;
        bob = malloc(SIZE);//how much memory you want , mention in SIZE variable.
        printf("enter the string\n");
        scanf("%s",bob);
        printf("%s\n", bob);

【讨论】:

  • scanf("%s",bob); 将无法成功扫描 "My name is bob!"bob 这样的文本。
  • 要扫描带空格的字符串而不是 scanf 我们应该使用 scanf("%[^\n]",bob)
  • scanf("%[^\n]",bob) 在以下情况下失败 1) 读取的前导字符是 '\n' 2) 它会将 '\n' 留在 stdin 中以供以后的 I/O 使用,而不是消耗它 3) 它不会阻止对bob 阅读过多。 fgets() 更好。
  • 同意@chux .. Fgets 是更好的选择。像 fgets(bob,size,stdin) 一样使用
【解决方案2】:

那是因为您必须设置起始值。
假设您有 char * a;
a 具有未定义的值,可能指向未经授权的区域。你不能在那里写。

你该怎么办?如果您必须使用 typedef char * string; ,则必须将其写入:
1) 动态堆,2) 堆栈上的缓冲区。

1) 使用 malloc - 一个必须从stdlib.h 中包含,并在动态堆中分配内存。该函数返回一个指向已分配内存开始的指针。
不要忘记在使用它释放分配的内存以避免泄漏后,free() 函数。

2) 声明一个预测的字符数组大小,并将其地址提供给您的变量。

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

#define MY_SIZE 50
typedef char * string;

int main() {
    string s;

    // 1)
    s = malloc(MY_SIZE);
    // some code
    free(s);

    // 2)
    char buf[MY_SIZE];
    s = buf;

    return 0;
}

你必须双向练习。
希望我有所帮助!

【讨论】:

  • s = &amp;buf; s/b s = buf;s = &amp;buf; 通常也会“工作”,但它会将错误的类型(指向 char 数组 50 的指针)分配给 char *
【解决方案3】:

使用 typedef 时如何从用户那里获取字符串? (typedef char * string;)

string bob需要被赋值,一个内存位置是用来存储读取的数据的。

#define N 80 

// local array
char buf[N];
string bob = buf;
fgets(bob, N, stdin); 

// or malloc
string bob = malloc(N);
if (bob == NULL) Handle_OutOfMemory(); 
fgets(bob, N, stdin); 

现在修剪潜在的'\n'

bob[strcspn(bob, "\n")] = '\0';

打印结果

printf("<%s>\n", bob);

...稍后再使用这些内容。

这意味着代码应该使用适当大小的内存分配,以便很好地传递此输入代码。 strdup() 不在标准 C 库中,但很常见。 Sample code.

 // local array approach
 bob = strdup(bob);
 // Now bob points to allocated memory

 // malloc approach
 // re-size to be efficient
 void *t = realloc(bob, strlen(bob) + 1);
 if (t) {
   bob = t;
 }
 // Detail: A realloc to a smaller amount of memory rarely ever fails.
 // If it did fail, just continue with old pointer.

如果bob 指向分配的内存,则在使用bob 完成后清理。

free(bob);

仅在需要时使用scanf(),并且您不能辍学或在其他地方找到工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 2019-07-03
    相关资源
    最近更新 更多