C语言二维数组城市名排序:错误赋值逻辑的原因解析
你作为C语言初学者,尝试对二维数组中存储的10个城市名做字典序排序,但原代码里的字符串交换逻辑无法运行,换成strcpy相关代码后就能正常工作。下面详细解释错误交换逻辑的问题所在。
原排序代码
#include<stdio.h> #include<string.h> int main(){ char str[10][20]={"mumbai","goa","kanpur","bhopal","delhi","nagpur","jabalpur","thane","bhandup","kurla"}; for(int i=0;i<10;i++) { for(int j=i+1;j<10;j++) { int p = strcmp(str[i],str[j]); if(p==-1 || p==0) continue; else { char tmp[1][20]; tmp[0] = str[i]; str[i] = str[j]; str[j]= tmp[0]; } } } for(int i=0;i<10;i++) { printf("%s\n",str[i]); } return 0; }
可正常运行的交换逻辑
char tmp[20]; strcpy(tmp, str[i]); strcpy(str[i], str[j]); strcpy(str[j], tmp);
错误交换逻辑的问题根源
1. C语言不允许直接给数组名赋值
在C语言里,数组名是指向数组首元素的常量指针,它代表的是数组在内存中的起始地址,这个地址是固定不可修改的。你试图用=给数组名赋值的操作,本质是在修改这个固定地址,完全违反C语言的语法规则。
比如tmp[0] = str[i];这行:tmp[0]是长度为20的char数组,str[i]也是char数组,两者都是数组名,直接用=赋值属于非法操作,编译器会抛出类似“数组类型不可赋值”的错误。同理,str[i] = str[j];和str[j] = tmp[0];这两行也都是在给数组名赋值,同样不被允许。
2. 字符串交换需要复制内容而非地址
二维数组str[10][20]里的每个str[i],是一块能存储20个字符的内存区域,城市名的字符数据就存在这里。你要交换两个城市名,本质是要把str[i]内存里的所有字符复制到临时区域,再把str[j]的内容复制到str[i],最后把临时区域的内容复制到str[j]。
strcpy函数的作用就是完成这种内存内容的复制:它会把源字符串的每个字符逐个复制到目标内存区域,操作的是数组里的字符数据,而非数组的地址,完全符合C语言的规则。
小建议:简化排序判断逻辑
原代码里的strcmp判断可以简化:当strcmp(str[i], str[j]) > 0时,说明str[i]的字典序比str[j]大,直接执行交换即可,不用写continue的分支,代码会更简洁。
内容的提问来源于stack exchange,提问作者satyam jha

