tandkzy 发表于 2007-7-21 16:13:20

关于strncpy的一些问题

函数说明如下:
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;
        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

loveccy 发表于 2007-7-22 11:26:35

兄弟,你的程序真是这么写的吗?那个 filename 是什么东西啊,char,指针,或是数组名?我没看明白那个循环是怎么结束的。呵呵,换个说法,这个程序很乱啊。

默难 发表于 2007-7-22 12:53:29


      for(i=0 ; filename != '\0' ; i++){
                if (filename == '*')
                        break;
      }

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

for(;*filename != 0; filename++)
if('*' == *filename)
    break;


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

tandkzy 发表于 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 编辑 ]

loveccy 发表于 2007-7-24 17:21:30

我用 Dev-C++ 4.9.9.2 的 MinGW (gcc 3.4.2-20040916-1)试了一下。#include <stdio.h>
#include <stdlib.h>

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

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

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

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

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

Mikeandmore 发表于 2007-7-24 20:57:38

无奈。。。。
这种恶心的编程方式MS一直是学校里教的。。。。。
即使是在名牌大学。。。大家MS一直只是强调程序的运行效率,结果。。。但是很少重视程序的可读性。。。

tandkzy 发表于 2007-7-25 15:33:09

原帖由 Mikeandmore 于 2007-7-24 20:57 发表 http://218.56.161.11/bbs/images/common/back.gif
无奈。。。。
这种恶心的编程方式MS一直是学校里教的。。。。。
即使是在名牌大学。。。大家MS一直只是强调程序的运行效率,结果。。。但是很少重视程序的可读性。。。

这段代码很难读懂么? :? :?

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

loveccy 发表于 2007-7-25 19:37:45

不会是说我那个试验的代码恶心吧……Mike 你说的 MS 是什么意思啊?

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

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

Mikeandmore 发表于 2007-7-28 18:34:25

原帖由 tandkzy 于 2007-7-25 15:33 发表 http://www.linuxfans.org/bbs/images/common/back.gif


这段代码很难读懂么? :? :?

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

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

      for(i=0 ; filename[i] != '\0' ; i++){
                if (filename[i] == '*')
                        break;
      }

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

      p=&filename[i+1];

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


      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。。。
页: [1]
查看完整版本: 关于strncpy的一些问题