使用命令行为 C 中的结构赋值

Assignment of values to structs in C using command line

我正在尝试使用命令行设置具有多个值的结构。当我在 MS 商店的 Ubuntu 18.04ls 终端中执行程序时,我给出了这些属性。但是我遇到了一个问题,因为我无法访问写在终端上的那些属性。

这是我的代码:

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

#define TAMANIOMAXIMO 20

struct persona {
  char nombre[TAMANIOMAXIMO];
  int edad;
  float ingresos;
}

main (int argc, char *argv[]) {
  printf("%d\n", argc);
  
  char nameProf[] = "";
  stpcpy(nameProf, argv[1]);
  int edadProf = atoi(argv[2]);
  float ingresosProf = atof(argv[3]);
  struct persona profesor = {nameProf, edadProf, ingresosProf};
  
  struct persona alumno;
  
  strcpy(alumno.nombre,"Juan");
  alumno.edad=19;
  alumno.ingresos=11.777;
  
  printf("Los ingresos conjuntos de alumnno y profesor son %f\n",alumno.ingresos+profesor.ingresos);
  exit(1);
} 

执行的结果是这个:

./a.out james 10 12
-691680792
Los ingresos conjuntos de alumnno y profesor son 11.777000

不知道为什么参数argc(存放argv的元素个数)有这个长度。我尝试删除 main 函数之前的结构 'persona' 的定义,一切都是正确的。 argv[1]、argv[2] 和 argv[3] 的内容不是在命令行中作为参数给出的,argv[0] 不存储“./a.out”,因为它应该存储。

因为忘记在struct后面加一个;,所以编译器认为struct是main的return类型

您还应该有 int main,而不仅仅是 main

解决项目中的问题的一个好的开始是打开编译器的警告(例如, -Wall-Werror)。

对于struct persona定义的右大括号,将}改为};以结束声明。

main (int argc, char *argv[]) 更改为 int main(int argc, char *argv[])。缺少分号和 int 导致 main 的错误声明可能会干扰向其传递参数,从而导致 argc 参数被错误地获取。

char nameProf[] = "";中,数组大小取自初始化器"",因此它只有一个元素,一个终止空字符。因为它只有一个元素,所以其中的 stpcpy 会破坏内存,导致您的程序运行异常。您可以将定义更改为 char nameProf[TAMANIOMAXIMO] = "";。但是,不需要这个数组,所以删除它和它后面的stpcpy即可。

struct persona profesor = {nameProf, edadProf, ingresosProf}; 中,您不能用另一个命名数组 (nameProf) 初始化数组(nombre 成员)。 (您可以使用字符串文字初始化 char 的数组,但这不是您想要的。)暂时只需将 nameProf 命名为 {0} 即可将数组初始化为零。然后,在这一行之后,用 strcpy(profesor.nombre, argv[1]); 将名称复制到数组成员中。 (这就是不需要 nameProf 的原因;您可以直接将命令行参数复制到结构成员中。)

打开编译器中的警告并注意它们。

如果我们在不做任何更改的情况下编译您的程序,但将 -Wall -Werror 传递给 gcc,我们会得到:

$ gcc -Wall -Werror -o scratch main.c
main.c:7:1: error: return type of 'main' is not 'int' [-Werror,-Wmain-return-type]
struct persona {
^
main.c:7:1: note: change return type to 'int'
struct persona {
^~~~~~~~~~~~~~
int
main.c:20:30: error: incompatible pointer to integer conversion initializing 'char' with an expression of type 'char [1]' [-Werror,-Wint-conversion]
  struct persona profesor = {nameProf, edadProf, ingresosProf};
                             ^~~~~~~~
main.c:20:30: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
  struct persona profesor = {nameProf, edadProf, ingresosProf};
                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                             {                               }
3 errors generated.

因此,只需将这些标志传递给 GCC,您就可以获得修复程序所需的所有信息。

您的程序存在多个问题,导致其行为未定义。我不清楚为什么未定义的行为具体表现为正在打印的意外值,但这完全在可能的 UB 范围内。

问题包括

  1. 正如@Gnoom 在他们的回答中指出的那样,您在 struct persona 的声明之后省略了一个分号,并且还省略了 main 的 return 类型。结果是语法正确的函数声明 return 是 struct persona,但是 main 是 return int.

    所必需的
  2. 此声明:

    char nameProf[] = "";
    

    charName 声明为一个数组,其长度刚好足以容纳一个空字符串,包括终止符 -- 也就是说,只有一个字节。这不足以容纳您稍后尝试读入的名称,因此您超出了该缓冲区。

  3. 这个声明中的初始化...

    struct persona profesor = {nameProf, edadProf, ingresosProf};
    

    ...没有达到您期望的效果。正如您不能通过 = 运算符将一个数组分配给另一个数组一样,您也不能通过将数组变量的标识符放入对应于该成员的初始值设定项来初始化数组或成员数组的元素。

您的编译器应该至少就其中一些警告您,您应该养成阅读编译器警告并确保您理解它们告诉您的内容的习惯。在您有更多经验之前,您应该假设每个警告都表示需要解决的问题,以免您的程序无法正常工作。