如何在C

时间:2017-11-25 06:41:53

标签: c string printing assign cs50

打印变量中保存的字符串的首字母(第一个字符)' fn'和变量' ln'

#include <stdio.h>
#include <cs50.h>

int main(void)
    {
        string fn, ln, initials;

        fn = get_string("\nFirst Name: ");
        ln = get_string("Last Name: ");

        initials = 'fn[0]', 'ln[0]';

        printf("%s", initials)

    }

2 个答案:

答案 0 :(得分:1)

详细了解C。特别是,阅读一些优秀的C编程书籍和一些C reference网站并阅读C11标准n1570。请注意,cs50.h不是标准C头(我从未遇到过它)。

string类型不存在。因此,您的示例不会编译,也不是有效的C代码。

C中一个重要的(也是困难的)概念是:undefined behavior(UB)。我不会在这里解释它是什么,但请参阅this,阅读更多关于UB的内容,并且真的害怕UB。

即使您(错误地)添加了类似

的内容
typedef char* string;

(您的cs50.h可能会这样做)您需要了解:

  • 并非每个指针都有效,并且某些指针可能包含无效地址(例如NULL或大多数随机地址;特别是未初始化的指针变量通常具有无效指针)。请注意,在virtual address space中,大多数地址都无效。取消引用无效指针是UB(通常但不总是给出segmentation fault)。

  • 即使指向char的指针有效,它也可能指向不是字符串的东西(例如,某些字节序列不是 NUL 终止)。将这样的指针(到非字符串数据)传递给字符串相关函数-e.g. strlenprintf%s为UB。

字符串是一个字节序列,带有其他约定:至少它应该 NUL 终止,并且您通常希望它是您系统的有效字符串。例如,我的Linux正在使用UTF-8(2017年UTF-8是used everywhere),所以实际上只有有效的UTF-8字符串可以在我的终端中正确显示。

数组被衰减为指针(阅读更多以了解这意味着什么,这很棘手)。因此,在某些情况下,您可能会声明一个数组变量(缓冲区)

 char buf[50];

然后填写它,可能使用strcpy喜欢

 strcpy(buf, "abc");

或使用snprintf之类的

 int xx = something();
 snprintf(buf, sizeof(buf), "x%d", xx);

和后者你可以用作“字符串”,例如

printf("buf is: %s\n", buf);

一些的情况下(但并非总是!),您甚至可以进行一些数组访问,例如

char c=buf[4];
printf("c is %c\n", c);

或像

这样的指针算法
printf("buf+8 is %s\n", buf+8);

BTW,由于stdio是缓冲的,我建议您使用printffflush结束\n控件格式字符串。

谨慎并谨慎对待buffer overflows。这是UB的另一个常见原因。

您可能想要声明

 char initials[8];

并填充该内存区域以成为正确的字符串:

 initials[0] = fn[0];
 initials[1] = ln[0];
 initials[2] = (char)0;

最后一次赋值(到initials[2])是将 NUL 终止字节并使initials缓冲区成为正确的字符串。然后,您可以使用printffputs

输出
fputs(initials, stdout);

你最好用

输出换行符
putchar('\n');

(或者你可能只做puts(initials); ....)

请编译所有警告和调试信息,gcc -Wall -Wextra -gGCC。改进您的代码以获得警告。了解如何use your compileryour debugger gdb。使用gdb逐步运行程序并查询其状态。花点时间阅读您正在使用的每个标准函数的documentation(例如strcpyprintfscanffgets),即使您最初不喜欢不明白所有这些。

答案 1 :(得分:-1)

char initials[]={ fn[0], ln[0], '\0'};

这将形成char数组,您可以使用

打印它
printf("%s", initials) //This is a string - null terminated character array.

string中没有c数据类型的概念。我们使用null terminated character array来模拟它。

如果你不将\0放在最后,它就不会是一个空终止的char数组,如果要打印它,你将不得不在数组中使用索引来确定个别角色。 (您不能使用printf或其他标准功能。

int s[]={'h','i'} // not null terminated
//But you can work with this, iterating over the elements.

for(size_t i=0; i< sizeof s; i++)
  printf("%c",s[i]);

为了进一步解释,string中没有C数据类型。所以你能做的就是用char []模拟它,这对于那项工作就足够了。

例如,你必须这样做才能得到一个字符串

char fn[MAXLEN}, ln[MAXLEN];

阅读输入可以是:

  if(!fgets(fn, MAXLEN,stdin) ){
    fprintf(stderr,"Error in input");
  }

对第二个char数组执行类似操作。

然后你形成了数组initials的初始化。

 char initials[]={fn[0],ln[0],'\0'}

null终止的char数组的好处是你可以将它传递给在char*上工作的函数并获得正确的结果。与strcmp()strcpy()一样。

还有很多方法可以从stdin获取输入,最好总是检查您使用的标准函数的返回类型。

标准不要限制我们所有char数组必须以null结尾。但如果我们不这样做那么它在常见情况下几乎没用。像我上面的例子。我之前显示的那个数组(没有空终止符)不能传递给strlen()strcpy()等。

在知情或不知不觉中,您使用了有趣的事情逗号运算符

假设你写了一个这样的状态

char initialChar = fn[0] , ln[0]; //This is error
char initialChar = (fn[0] , ln[0]); // This is correct and the result will be `ln[0]`

,运算符首先尝试计算第一个表达式fn[0],然后移动到第二个ln[0],并将该值作为整个表达式的值返回到initialChar

您可以查看这些有用的链接,以便开始使用