QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3674|回复: 8

关于strncpy的一些问题

[复制链接]
发表于 2007-7-21 16:13:20 | 显示全部楼层 |阅读模式
函数说明如下:
strncpy(拷贝字符串)  
   相关函数  
   bcopy,memccpy,memcpy,memmove
    表头文件  
   #include<string.h>
   定义函数  
   char * strncpy(char *dest,const char *src,size_t n);
   函数说明  
   strncpy()会将参数src字符串拷贝前n个字符至参数dest所指的地址。
   返回值  
   返回参数dest的字符串起始地址。

但是我在使用这个函数时发现一个很搞笑的问题。我的代码如下

......
        for(i=0 ; filename != '\0' ; i++){
                if (filename == '*')
                        break;
        }
        p=&filename[i+1];
        strcpy(extname,p);
        strncpy(mainame,filename,i);
........
这段代码的目的是从一个长字符串中定位*的位置,然后按*把该长串分成两个小串(有点像flashget里面处理批量任务的形式)。这段代码编译可以通过。当输入形为abc*.jpg时,该函数正常。
即mainame为abc
但是当输入一段长的网址代码时,该函数表现很奇怪。
例如输入http://comic.qq.com/images/comic/2007/02/02/cg/comicqq*.jpg
则使用strncpy后,mainame字符串的内容是这样的
http://comic.qq.com/images/comic/2007/02/02/cg/comicqq{懣"h鸱紒t懣PF穹}
花括号里是随机出现的乱码。每一次都不同~~~


请各位路过的大侠来看一看,告诉小弟这是什么原因~~~~
我的系统是magic2.01
发表于 2007-7-22 11:26:35 | 显示全部楼层
兄弟,你的程序真是这么写的吗?那个 filename 是什么东西啊,char,指针,或是数组名?我没看明白那个循环是怎么结束的。呵呵,换个说法,这个程序很乱啊。
回复

使用道具 举报

发表于 2007-7-22 12:53:29 | 显示全部楼层

  1.         for(i=0 ; filename != '\0' ; i++){
  2.                 if (filename == '*')
  3.                         break;
  4.         }
复制代码

这是什么-_-#
你是不是想说(我就不缩进了):

  1. for(;*filename != 0; filename++)
  2.   if('*' == *filename)
  3.     break;
复制代码


至于后面的代码和你的解释,我就不知所云了……你给我个示例输入和示例输出我看看吧
回复

使用道具 举报

 楼主| 发表于 2007-7-23 17:04:41 | 显示全部楼层
不好意思。那里写错了。事实上filename是一个字符串(数组)。而p是一个字符型指针。正确的代码如下。(因为英文的数组下标被系统认为是一个说明了,没法,只好改成中文字符的下标了)

"......
        for(i=0 ; filename[i] != '\0' ; i++){
                if (filename[i] == '*')
                        break;
        }
        p=&filename[i+1];
        strcpy(extname,p);
        strncpy(mainame,filename,i);
........"

这段代码是我用来处理链接地址的。目的是要把输入的地址拆成“路径/主名"和"扩展名"。而星号'*'是用来指示某一处要用数字序列的位置的。很多图片站点的图片都有这样的规律,图片文件都是顺序排列的,只有编号不同。而星号正是代表着编号的位置。

我的问题是,如果用abc*.jpg这样的字符串来测试这一段代码,则strncpy输出的结果是abc,也就是说是正确的结果。但是如果是用真正的地址,例如下面这一段:
http://comic.qq.com/images/comic/2007/03/27/yy/*.jpg
那么就通过strncpy就会出现这样的结果:
http://comic.qq.com/images/comic/2007/03/27/yy/8~9个字符乱码

[ 本帖最后由 tandkzy 于 2007-7-23 17:12 编辑 ]
回复

使用道具 举报

发表于 2007-7-24 17:21:30 | 显示全部楼层
我用 Dev-C++ 4.9.9.2 的 MinGW (gcc 3.4.2-20040916-1)试了一下。
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main(int argc, char *argv[])
  4. {
  5.         char mainame[1024];
  6.         char extname[1024];
  7.         char *filename = "http://comic.qq.com/images/comic/2007/03/27/yy/*.jpg";
  8.         char *p;
  9.         int i;

  10.         for(i=0 ; filename[i] != '\0' ; i++){
  11.                 if (filename[i] == '*')
  12.                 break;
  13.         }
  14.         p=&filename[i+1];
  15.         strcpy(extname,p);
  16.         strncpy(mainame,filename,i);

  17.         printf ("%s\n%s\n", mainame, extname);

  18.         system("PAUSE");
  19.         return 0;
  20. }
复制代码
输出结果是
  1. http://comic.qq.com/images/comic/2007/03/27/yy/
  2. .jpg
复制代码
好像没碰到你说的问题啊。

那个,你想没想过万一 filename 字符串里边要是没有 '*' 会发生什么事?标准库里边有一些函数,比如 strchr, strstr, strtok 等。学 C 语言还是挺好玩的,呵呵。一块儿加油啊!
回复

使用道具 举报

发表于 2007-7-24 20:57:38 | 显示全部楼层
无奈。。。。
这种恶心的编程方式MS一直是学校里教的。。。。。
即使是在名牌大学。。。大家MS一直只是强调程序的运行效率,结果。。。但是很少重视程序的可读性。。。
回复

使用道具 举报

 楼主| 发表于 2007-7-25 15:33:09 | 显示全部楼层
原帖由 Mikeandmore 于 2007-7-24 20:57 发表
无奈。。。。
这种恶心的编程方式MS一直是学校里教的。。。。。
即使是在名牌大学。。。大家MS一直只是强调程序的运行效率,结果。。。但是很少重视程序的可读性。。。


这段代码很难读懂么?

我并不觉得学校里教的有什么不对的地方。只不过,就我在大学里学的那点三脚猫的C,要编这么个简单的程序只怕还不那么容易。我不是说大学里的C教材写得不好。其实谭浩强教授的C教材是很容易懂的。只不过,谭教授太过于把教材写得简单了,结果一些重要的地方却没有照顾到了。例如说C中没有字符串类型的变量,只有字符字组。而实际应用中,我们在C中所用到的字符串,又都是要以一个特殊字符'\0'来结束的字符数组。(后面这一点,我看了好几版的教材,都没有提到或者只是一句简单的话带过了)而现行大学里的C教材,那里面的习题真叫一个费解。学计算机又不是学数学,没想到教材上的题目居然大部分是要学生去解决数学问题~~~
自己买了一本中文版的《C 编程语言》来看,这才发现原来C可以这么强大,原来字符串的处理这么重要。这本老美的专业C语言著作里面,几乎不会要你解什么数学题,但是它讲的例子,每一只都是根据实际应用来的,你甚至可以直接用你抄来的程序稍作修改来代替相应的一些UNIX、Linux命令!而这些还仅仅是标准C~~~
回复

使用道具 举报

发表于 2007-7-25 19:37:45 | 显示全部楼层
不会是说我那个试验的代码恶心吧……Mike 你说的 MS 是什么意思啊?

看 "The C Programming Language" 就对了。谭老的书好多地方讲得不准确或不透彻,也就是用来应付无聊的等级考试,真想学 C 语言不应该用谭老的书。

不过兄弟,你得知道,老外那本书讲的仅仅是 C 语言本身而已。想解决实际的问题,数学什么的还是要学的。学计算机就是要学数学。建议你还应该看 "The Practice of Programming" (程序设计实践)。
回复

使用道具 举报

发表于 2007-7-28 18:34:25 | 显示全部楼层
原帖由 tandkzy 于 2007-7-25 15:33 发表


这段代码很难读懂么?

我并不觉得学校里教的有什么不对的地方。只不过,就我在大学里学的那点三脚猫的C,要编这么个简单的程序只怕还不那么容易。我不是说大学里的C教材写得不好。其实谭浩强教授 ...


恩。。。要是想让你明白我的意思看来就得举例了。。。

  1.         for(i=0 ; filename[i] != '\0' ; i++){
  2.                 if (filename[i] == '*')
  3.                         break;
  4.         }
复制代码

1 尽量不要用循环来查找字符串。。。strstr是干什么的?
2 在没有特殊需求的情况下尽量不要为for循环添加break。。。否则要添加注释

  1.         p=&filename[i+1];
复制代码

你听说过'&' is evil么?。。。
原因就是&取得的地址是没有指明地址的位置的。它有可能在static pool, system heep 和 runtime stack中。。。这样你也不知道应该不应该free。。。
在这样简单的一个程序中用&这样极难以驾驭的东西,不是很爽吧。。。


  1.         strcpy(extname,p);
复制代码

这个不用我说了吧。。。已经是很经典的问题了。。。
在extname和p的大小没有确定的情况下会出现buffer overflow。。。(这个很多教材都会讲的)

我学C语言的体会是:C语言太难了。它不像C++那样复杂,但是由于过于的底层,出现了很多让人很难掌握的东西。
举一个高端的例子(这个例子中C++也没有搞定。。。但是Java是可以的)
比如一个多线程程序。每一个子线程在竞争数据访问的时候本身可以用mutex来避免数据的竞争修改。
但是由于编译器的优化只能保证每个线程的单独执行结果不变,但是优化可能是数据跑出mutex的范围。
这就是因为C/C++的内存管理是但线程的没有一个数据线程量。而Java语言则可以不考虑该问题,因为Jvm的内存是多线程模型。
具体的可以看看BH的 Thread CANNOT be implement as a library。。。
回复

使用道具 举报

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

本版积分规则

GMT+8, 2024-11-2 00:36 , Processed in 0.135317 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

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