鱼C论坛

 找回密码
 立即注册
查看: 2867|回复: 9

[已解决]多维数组存放汉字问题

[复制链接]
发表于 2022-4-13 17:50:15 | 显示全部楼层 |阅读模式
5鱼币
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         char chr[2][10];

  5.         chr[0] = "黑桃";
  6.         chr[1] = "红桃";

  7.         printf("%s\n%s\n", chr[0], chr[1]);

  8.         return 0;
  9. }
复制代码

  1. #include <stdio.h>

  2. int main()
  3. {
  4.         char chr[2][10] = {{"黑桃"}, {"红桃"}};

  5.         printf("%s\n%s\n", chr[0], chr[1]);

  6.         return 0;
  7. }
复制代码


为什么上面代码不行啊?报错如下
  1. assignment to expression with array typ
复制代码

顺带问一下,我在fishc写日志,tab键不是缩进,而是在切换选中的按钮?但是写帖子tab就是缩进。
还有,C语言里有像python中字符串的format方法吗?在C里面是不是得自己写函数实现啊???

最佳答案
2022-4-13 17:50:16
本帖最后由 AnisHan 于 2022-4-15 11:35 编辑

对于字符数组你需要使用指针数组而不是二维数组,声明这样写char szBuffer[] = "";可以,但是赋值就有问题。因为数组不能直接赋值.
你应该也知道int a[] = {1, 2, 3} int b[3] = a这么写是错的吧,数组是一个常量指针(数组确实是这么指向内存的,你这么想就行了,实际上肯定还是要复杂得多),你不能直接把数组原本指向的指针硬改成指向“字符串常量池:的指针(字符串一般是以\0结尾的数组你应该知道吧,数组传值的时候是地址传递值不是数组里的值传递,“xxx” 这样声明的字符串是在字符串常量池中的)你这种写法就是用字符串常量池中的字符串数组地址替换掉要赋值数组的地址,很明显这样乱搞会导致程序结构很乱,内存空间也是指来指去乱七八糟,所以c语言不允许


解决:请这么写
        char *szStrArr[10]; //这个指针数组,因为指针可以改随便改指向的内容的

关于格式化字符串: sprintf(char * buffer, char * format, ...)(参数名字自己起的,类型可能多个const什么的,但是不重要)或者wsprintf(参数较为“特殊”不是很好写)具体使用方法你百度一下就知道了,和printf用法很类似,wsprintf是通用字符版本,一般这两个函数都有溢出风险(可以修改你函数跳转地址,注入并且执行恶意代码的函数),解决就是vs可以用 strsafe.h 的 StringCchPrintf,具体方法百度吧。


还有就是,建议中文使用宽字符,普通字符串可能会导致乱码,比如文档是UFT-8编码的你的系统是GBK的,那就可能乱码了,如果文档和系统(就是说shell/console)都是一种编码那就不会乱码


还有理论上你第二个那种写法应该是可以的

最佳答案

查看完整内容

对于字符数组你需要使用指针数组而不是二维数组,声明这样写char szBuffer[] = "";可以,但是赋值就有问题。因为数组不能直接赋值. 你应该也知道int a[] = {1, 2, 3} int b[3] = a这么写是错的吧,数组是一个常量指针(数组确实是这么指向内存的,你这么想就行了,实际上肯定还是要复杂得多),你不能直接把数组原本指向的指针硬改成指向“字符串常量池:的指针(字符串一般是以\0结尾的数组你应该知道吧,数组传值的时候是地址传 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-13 17:50:16 | 显示全部楼层    本楼为最佳答案   
本帖最后由 AnisHan 于 2022-4-15 11:35 编辑

对于字符数组你需要使用指针数组而不是二维数组,声明这样写char szBuffer[] = "";可以,但是赋值就有问题。因为数组不能直接赋值.
你应该也知道int a[] = {1, 2, 3} int b[3] = a这么写是错的吧,数组是一个常量指针(数组确实是这么指向内存的,你这么想就行了,实际上肯定还是要复杂得多),你不能直接把数组原本指向的指针硬改成指向“字符串常量池:的指针(字符串一般是以\0结尾的数组你应该知道吧,数组传值的时候是地址传递值不是数组里的值传递,“xxx” 这样声明的字符串是在字符串常量池中的)你这种写法就是用字符串常量池中的字符串数组地址替换掉要赋值数组的地址,很明显这样乱搞会导致程序结构很乱,内存空间也是指来指去乱七八糟,所以c语言不允许


解决:请这么写
        char *szStrArr[10]; //这个指针数组,因为指针可以改随便改指向的内容的

关于格式化字符串: sprintf(char * buffer, char * format, ...)(参数名字自己起的,类型可能多个const什么的,但是不重要)或者wsprintf(参数较为“特殊”不是很好写)具体使用方法你百度一下就知道了,和printf用法很类似,wsprintf是通用字符版本,一般这两个函数都有溢出风险(可以修改你函数跳转地址,注入并且执行恶意代码的函数),解决就是vs可以用 strsafe.h 的 StringCchPrintf,具体方法百度吧。


还有就是,建议中文使用宽字符,普通字符串可能会导致乱码,比如文档是UFT-8编码的你的系统是GBK的,那就可能乱码了,如果文档和系统(就是说shell/console)都是一种编码那就不会乱码


还有理论上你第二个那种写法应该是可以的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-13 18:29:55 | 显示全部楼层
因为chr[0]和chr[1]是地址常量,不可能给常量赋值
建议用指针实现
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         char *chr[2];
  5.         chr[0] = "黑桃";
  6.         chr[1] = "红桃";

  7.         printf("%s\n%s\n", chr[0], chr[1]);
  8.         return 0;
  9. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-13 23:06:49 | 显示全部楼层
"黑桃" 是个字符串,通常来讲 "黑桃"占4个字符,chr[0] 也就只能保存一个字符吧。

参考:

https://www.cnblogs.com/pam-sh/p/15034330.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-14 09:27:25 | 显示全部楼层
上面那个先定义了数组再赋值是错的。因为数组是不能直接整体赋值的类型,结构体也同理。
都只能在初始化的时候进行赋值。若要为其填充数据的话可以自己写循环或者调用一些字符串
的格式化函数来填充。像什么strcpy等等,在标准库<string.h>中。你可以看看甲鱼的文档。
至于上述的原因,深层的涉及到原理的我也不清楚,但是C语言的标准文档里面是有写的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-14 17:08:56 | 显示全部楼层

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

int main()
{
        char chr[2][10];

        strcpy(chr[0] , "黑桃");
        strcpy(chr[1] , "红桃");

        printf("%s\n%s\n", chr[0], chr[1]);

        return 0;
}
改一下就可以了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-4-14 23:33:51 | 显示全部楼层
AnisHan 发表于 2022-4-14 10:07
对于字符数组你需要使用指针数组而不是二维数组,声明这样写char szBuffer[] = "";可以,但是赋值就有问题 ...

第二个写法是可以,是我表述不清,是第一个代码段的代码报错。
你说的第一段我还能大概看懂,第二段我就没接触过了,一点也不了解,我才学到 “带你学C带你飞” 的函数,头文件是什么我还不知道。其他答案写的什么结构体什么的我也一头雾水。
你说的这些文档、系统、编码、程序结构、常量池……什么的,该去学什么才会了解啊。看完 “带你学C带你飞” 是不是只是了解了基础的语法,知道怎么个用法?这些 文档…… 应该接着学什么啊?我不知道学习路线,能指个路吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-15 08:28:16 | 显示全部楼层
本帖最后由 AnisHan 于 2022-4-15 11:38 编辑
孤不冷cing 发表于 2022-4-14 23:33
第二个写法是可以,是我表述不清,是第一个代码段的代码报错。
你说的第一段我还能大概看懂,第二段我就 ...


你跟着学就行,这些常量池是其他语言内容(毕竟c的有的字符串不是常量,一般单独的写的字符串常量位于代码区,数组直接赋值的字符串是数组的内存,此时一般不是常量),应该小甲鱼的扩展阅读或者讲课的时候都有提到过c语言内存结构,只是这样申请的字符串不和普通变量在一起。
只不过觉得能让你好理解,我还是直接用数组简单的说一下吧, 这样申请的字符串“xx”就是一个以\0结尾的完整的数组,所以 你这么写就是这样赋值
char b[10];char a[] = b。这就是硬改数组原本指向的数据
不过这样的char a[] = "xxx"申请的就是和普通变量在一起的,这是创建数组 等于 = {''x', 'x', 'x", \0"}; 具体为什么这两个结果不一样,这可能是C语言底层内容了。

其实这不重要,你知道字符串数组使用 字指针数组 就行了
关于学习路线我也不是什么权威人士不敢瞎说,反正额我线路就是
c语言 -> 系统API编程(Windows sdk/linux),完事我就去学C++了hhh
其实我是从Java跳过来的,我懒得学Web了,所以学完QT估计就回到WEB开发了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-15 08:41:40 | 显示全部楼层
孤不冷cing 发表于 2022-4-14 23:33
第二个写法是可以,是我表述不清,是第一个代码段的代码报错。
你说的第一段我还能大概看懂,第二段我就 ...

编码是我学Windows SDK了解的,文件是C语言本身就有流对象 FILE,fopen,常量池是Java的,小甲鱼的c主要需要你看论坛里的文章课后作业,我也不能给你推荐别的对吧,这是人家的论坛。

其实小甲鱼c的基础语法除了c11新增的东西,都差不多了。具体写别的东西(多线程,窗口应用)需要用API什么的了,至于写系统写驱动,我不会,我感觉如果不是在系统上运行的话是需要汇编学习的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-4-15 10:09:56 | 显示全部楼层
AnisHan 发表于 2022-4-15 08:41
编码是我学Windows SDK了解的,文件是C语言本身就有流对象 FILE,fopen,常量池是Java的,小甲鱼的c主要 ...

噢噢,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-6 04:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表