寒假作业Day 03
一、选择题
在C语言中,字符型指针char *p;通常用于指向字符数组(即字符串)的首字符。对于给定的选项,我们来分析每一个选项是否可以将字符串正确地赋值给p:
A: p=getchar();
getchar()函数从标准输入读取一个字符,并返回该字符的ASCII值。由于getchar()返回的是一个int类型的值(它可能是EOF,即文件结束标记,这是一个负值),所以直接将这个返回值赋给char *类型的p是不正确的。此外,即使忽略类型不匹配的问题,getchar()也仅仅读取一个字符,而不是整个字符串。
B: scanf(“%s”,p);
这个语句试图从标准输入读取一个字符串并存储在p指向的位置。然而,这个语句有潜在的风险。因为p没有被初始化指向一个有效的内存区域(即一个足够大的字符数组),scanf可能会写入一个随机的内存位置,这可能会导致程序崩溃或未定义的行为。
C: char s[]=“china”; p=s;
这个语句是正确的。它首先定义了一个字符数组s并初始化为字符串"china"。然后,它将p指向s的首字符,即s[0](即’c’)。这样,p就指向了一个有效的字符串。
D: *p=“china”;
这个语句是错误的。首先,*p表示p指向的字符,它是一个char类型的变量。然而,字符串"china"是一个字符数组,不是一个单个的字符。此外,你不能直接将一个字符串字面量赋给一个char类型的变量。
综上所述,选项A、B和D都不能正确地将字符串赋值给字符型指针p。因此,正确答案是A、B和D。
接下来,我们逐步分析:
static char *s[] = {“black”, “white”, “pink”, “violet”};
这里定义了一个静态的字符串数组s,包含四个字符串元素。
char **ptr[] = {s+3, s+2, s+1, s}, ***p;
这里定义了一个名为ptr的指针数组,每个元素都是一个指向字符指针的指针。s+3、s+2、s+1和s分别指向s数组中的第四个、第三个、第二个和第一个字符串的起始地址。
所以,ptr数组的内容如下:
* ptr[0] 指向 "violet"
* ptr[1] 指向 "pink"
* ptr[2] 指向 "white"
* ptr[3] 指向 "black"
- p = ptr;
这里定义了一个名为p的指针,它指向一个指针的指针。然后将p指向ptr。- ++p;
将p的值增加1,由于p是一个指向指针的指针的指针,所以p现在指向ptr数组的下一个元素,即ptr[1],它指向"pink"。- printf(“%s”, **p+1);
这里有两个*,所以**p首先解引用p,得到ptr[1],然后再次解引用得到"pink"。接着,**p+1将指针向前移动一个字符,指向’i’。因此,输出的是从’i’开始的字符串,即"ink"。
总结:该程序的输出是"ink"。
首先分析语句,char s[3][10]是一个3行10列的二维字符数组,char (*k)[3]是一个包含3个元素的字符指针数组,char *p是一个字符指针;
分析选项:1、p = s;:这是错误的。s是一个二维数组,其名字s在大多数上下文中会被解释为指向其首行(即s[0])的指针,该指针的类型是char ( *)[10](指向包含10个字符的数组的指针)。但p是一个char *,即指向单个字符的指针。类型不匹配,所以这是错误的。
2、p = k;:这也是错误的。k是一个指向包含3个字符的数组的指针,即char ( *)[3]。但p是一个指向单个字符的指针,即char * 。类型不匹配。
3、p = s[0];:这是正确的。s[0]是s的第一行,它是一个包含10个字符的一维数组。在大多数上下文中,数组名s[0]会被解释为指向其首元素的指针,即指向s[0][0]的指针。这个指针的类型是char *,与p的类型相同。
4、k = s;:这也是错误的,尽管可能看起来是正确的。s的名字在大多数上下文中会被解释为指向其首行(即s[0])的指针,其类型是char ( * )[10](指向包含10个字符的数组的指针)。但k的类型是char ( *)[3],即指向包含3个字符的数组的指针。尽管s的首行确实有3个字符的空间(实际上是10个),但k和s的指针类型并不匹配,因此这是错误的。
故选择答案A,只有选项3是正确的
4、假设 sizeof(void * ) 为4, sizeof(char) 为1,那么对于 char str[sizeof(“ab”)]; , sizeof(str) 的值是( )
A: 2 B: 3 C: 4 D: 代码无法编译
sizeof(“ab”)的值为3,其中有a,b和\0;char str[3],即str是有3个元素的字符数组,故sizeof(str)的值为3*1=3,选B
5、有如下程序段,则对函数 fun 的调用语句正确的是【多选】( )
char fun(char *);
int main()
{char *s = "one", a[5] = {0}, (*f1)(char *) = fun, ch;return 0;
}
A: * f1(&a); B: f1( * s); C: f1(&ch); D: ch = * f1(s);要改成( * f1)(s)才正确
首先,我们分析给定的程序段:
定义了一个函数fun,它接受一个字符指针作为参数,并返回一个字符。
在main函数中:
定义了一个字符指针s,指向字符串"one"。
定义了一个字符数组a,大小为5,并全部初始化为0。
定义了一个函数指针f1,它指向函数fun。这意味着f1可以用来调用fun函数。
定义了一个字符变量ch。
接下来,我们分析每个选项:
A: *f1(&a);
这是错误的。因为&a得到的是指向数组a的指针,但它的类型是char (*)[5],而不是char *。此外,*f1的解引用方式也是不正确的,应该是(*f1)(…)。
B: f1(*s);
这是错误的。*s得到的是s指向的字符串的第一个字符,即’o’。但fun函数期望一个字符指针作为参数,而不是一个字符。此外,调用函数指针的正确方式是(*f1)(…)。
C: f1(&ch);
这是错误的。虽然&ch得到的是一个字符指针,但是调用函数指针的正确方式是(*f1)(…)。
D: ch = *f1(s); 要改成 ( f1)(s) 才正确。
原始表达式f1(s)是错误的,因为它试图先调用函数然后解引用返回的结果,但函数的返回类型不是指针。正确的调用方式是(*f1)(s),并且由于fun的返回类型是char,所以可以将返回值赋给ch,即ch = (*f1)(s);
二、编程题
方法1:qsort排序之后使用strcmp比较两个字符串
int cmp(const void* _a,const void * _b){char a=*(char*)_a,b=*(char*)_b;return a-b;
}bool CheckPermutation(char* s1, char* s2){if(strlen(s1)!=strlen(s2))return false;qsort(s1,strlen(s1),sizeof(char),cmp);qsort(s2,strlen(s2),sizeof(char),cmp);return strcmp(s1,s2)==0;
}
方法二:哈希表
如果两个字符串中的字符重新排列后相等,其实也就说明其中的字符种类和其数量是一致的,所以我们可以用一个频次数组来记录,在s1数组中碰到字符就增加其频数,而在s2中则是减少频数,如果其中一个频数小于0,就说明两者不相等
bool CheckPermutation(char* s1, char* s2){if(strlen(s1)!=strlen(s2))return false;int table[128]={0};for(int i=0;i<strlen(s1);i++){table[s1[i]]++;//对应下标频数增加}for(int i=0;i<strlen(s2);i++){table[s2[i]]--;//对应下标频数减少if(table[s2[i]]<0)return false;}return true;
}
哈希表
我们举出几个回文数的例子,比如abccba,abcccba,a和不是回文数的例子,比如ab,abc,abcd,abcddeba…我们会发现,如果是回文数,顶多有一个数出现的次数为奇数;而如果不是,则一定会出现两个及以上的数出现的次数为奇数,通过这个,我们可以用哈希表记录频数,并记录奇数次的个数
bool canPermutePalindrome(char* s){int table[128]={0};int count=0;for(int i=0;i<strlen(s);i++){table[s[i]]++;}for(int i=0;i<128;i++){if(table[i]%2==1){count++;}if(count>=2){return false;}}return true;
}