打印变量中保存的字符串的首字母(第一个字符)' 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)
}
答案 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. strlen
或printf
与%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是缓冲的,我建议您使用printf
或fflush结束\n
控件格式字符串。
谨慎并谨慎对待buffer overflows。这是UB的另一个常见原因。
您可能想要声明
char initials[8];
并填充该内存区域以成为正确的字符串:
initials[0] = fn[0];
initials[1] = ln[0];
initials[2] = (char)0;
最后一次赋值(到initials[2]
)是将 NUL 终止字节并使initials
缓冲区成为正确的字符串。然后,您可以使用printf
或fputs
fputs(initials, stdout);
你最好用
输出换行符putchar('\n');
(或者你可能只做puts(initials);
....)
请编译所有警告和调试信息,gcc -Wall -Wextra -g
与GCC。改进您的代码以获得警告。了解如何use your compiler和your debugger gdb
。使用gdb
逐步运行程序并查询其状态。花点时间阅读您正在使用的每个标准函数的documentation(例如strcpy
,printf
,scanf
,fgets
),即使您最初不喜欢不明白所有这些。
答案 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
。
您可以查看这些有用的链接,以便开始使用