疯狂的事情 [英] Crazy stuff

查看:66
本文介绍了疯狂的事情的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有这个(请忍受我 - 这是一个前java的案例

家伙回到C ;-)


int main(){

char * tokconvert(char *);

char str [] =" dot.delimited.str" ;;

char * result;


result = tokconvert(str);

返回0;

}


char * tokconvert(char * strToConvert){


char * token;

char * tokDelim =",。" ;;


token = strtok(strToConvert,tokDelim);


while(令牌!= NULL){

printf( 令牌 - >%s \ n,令牌);

token = strtok(NULL,tokDelim);

}

这个东西编译并且运行正常,但是如果我声明char * str =

" dot.delimited.str" (而不是char str [] =" dot.delimited.str")

整个事情都落在它的屁股真正的坏(总线错误) - strtok定义

作为char * strtok(char *,const char *) - 发生了什么?


更疯狂:如果我宣布/初始化


char * str;

str = strdup(" dot.delimited.str)


里面tokconvert(而不是main)并将其传递给strtok - 它运行

罚款!!


任何想法都是最受欢迎的..


chumbo。


PS

顺便说一下这是在FreeBSD 5.1.2上(使用gcc 3.3.3)

解决方案

Chumbo写道:

该东西编译并运行正常,但是如果我声明char * str =
dot.delimited.str (而不是char str [] =" dot.delimited.str")
整个事情都落在它的屁股真正的坏(总线错误) - strtok被定义为char * strtok(char *, const char *) - 发生了什么?




char * str =" blah";


是允许放在只读内存中。数据无法修改。


char str []但是,必须放在你可以修改的内存中(即

堆栈)。


-

Jason Whitehurst


Jason Whitehurst写道:

是允许的放在只读存储器中。数据无法修改。




Err,如果您不知道,strtok(3)修改输入字符串。因此,

你的问题。


-

Jason Whitehurst


< blockquote>文章< 50 ************************** @ posting.google.com>,

Chumbo< ch ********* @ hotmail.com>写道:

如果我有这个(请耐心等待 - 这是一个以前的java
家伙回到C的情况;-)
int main (){* char * tokconvert(char *);


如果你将函数原型放在文件范围内而不是内部函数,那么会减少人们的注意力。 (在这种特殊情况下,你可以通过在main()之前放置tokconvert,

来完全避免需要原型的
,但这并不总是可行或合理的。)

char str [] =" dot.delimited.str" ;;


这会分配一个char数组,并用字符串dot.delimited.str中的字符

填充它。 (包括终止''\ 0'')。

数组位于自动分配空间(我们可以称之为

堆栈,但是我们不喜欢,因为它存在的函数调用堆栈与处理器的堆栈段

堆栈不同甚至不存在)人们通常认为我们在讨论这个问题,因此我们可以做任何我们想要的事情(相关的比特)这里是我们可以写的)

直到函数返回。

char * result;

result = tokconvert(str) ;


当你将str(一个数组)传递给一个函数(或者使用

做大多数其他事情时,值得注意的例外是&或sizeof to it ),数组名称

衰减到指向数组第一个元素的指针。在这种情况下,这个

正是你想要的 - 指向字符串第一个字符的指针。

返回0;
}

char * tokconvert(char * strToConvert){

char * token;
char * tokDelim =",。" ;;

token = strtok (strToConvert,tokDelim);

while(令牌!= NULL){
printf(" Token - >%s \ n",令牌);
令牌= strtok(NULL,tokDelim);
}


你在这里没有回复任何东西。你的编译器应该警告你

你这个。

(我不知道你想要什么回来;可能这是剩下的

除了打印它们之外还用令牌做什么?)

}


东西编译并且运行正常,但是如果我声明char * str =
" dot.delimited.str" (而不是char str [] =" dot.delimited.str")
整个事情都落在它的屁股真正的坏(总线错误) - strtok被定义为char * strtok(char *, const char *) - 发生了什么事?


当你说`char * str ="一个字符串文字'''时,字符串文字(比如

程序中的任何其他字符串文字[ 1])指匿名

不包含但不可写的包含字符串的字符数组。

在英语中,这意味着你被允许指向一个你允许写入的指针(记住,数组衰减到指针),

但你实际上并没有被允许写入它。


所以,你有一个指针指向一个字符串文字,你不能写入... b $ b允许写入...然后你试试写入它(间接地,通过将​​它传递给strtok,它写入第一个参数)来获得
。那是'b $ b'导致你问题的原因。解决办法是不要那样做,然后:

为你给strtok作为第一个

参数的字符串分配可写空间,作为自动变量(如在上面的代码中)

或动态分配的内存(f'例如,来自strdup的内存为

以下),并将字符串放入其中。


更疯狂:如果我声明/初始化

char * str;
str = strdup(" dot.delimited.str)
很好!!


请注意strdup是一种单纯性而不是C语言的一部分。[2]


strdup做的是分配(使用malloc)足够的内存来保存你给它的字符串,并将字符串复制到该内存中,并返回一个

指针指向该字符串的副本。这个内存是可写的,所以给出

strdup指向它的指针不是问题,因为给出

它指向自动分配的数组的指针是同样的'问题。


PS
顺便说一下这是在FreeBSD 5.1.2上(使用gcc 3.3.3)




如果我需要知道这一点,那么你的问题将是

不适合comp.lang.c并且会更好的问候

a FreeBSD或者GCC新闻组。


但是考虑到你正在使用GCC:如果你编译的是:

gcc -W -Wall -ansi - 迂腐-O myprog.c

然后GCC会警告你没有从

tokconvert返回一个值,还有一些关于你的事情的其他警告/>
通常不想这样做。这使得调试一些问题变得更加容易 - 当编译器停止向你发出警告时它们会消失。

dave


[1]在language-lawyer-ese中,数组初始化中的字符串

`char buf [] ="字符串''是初始值设定项,而不是字符串文字;

据我所知,这是唯一可以在

中使用字符串的地方,这个源代码不代表匿名的char数组。


[2]但它在实现的命名空间中,这意味着你不能自己定义它。
不允许自己定义它。 comp.lang.c中的解决方案是

使用my_strdup,它可以被定义并且具有与unix strdup相同的

行为; comp.lang.c

之外的常用解决方案是使用库的strdup(如果存在),否则应用

知识超出语言定义中的知识建立

,允许程序员在

上用该名称定义一个函数,实现并执行此操作。


- -

Dave Vandervies dj******@csclub.uwaterloo.ca

嗯,这很少见。通常的反应是让我告诉你一点......

是Rich!丰富!我们***相信你,好吗?!?!?!?!?!"

- 在comp.lang.c中的理查德希思菲尔德


If I have this(please bear with me - this is a case of a former java
guy going back to C ;-)

int main () {
char *tokconvert(char*);
char str[] = "dot.delimited.str";
char *result;

result = tokconvert(str);
return 0;
}

char *tokconvert(char *strToConvert) {

char *token;
char *tokDelim =",.";

token=strtok(strToConvert, tokDelim);

while(token != NULL) {
printf("Token -> %s \n", token);
token=strtok(NULL, tokDelim);
}
}

the thing compiles and runs fine, however if I declare char *str =
"dot.delimited.str" (instead of char str[] = "dot.delimited.str") the
whole thing falls on its ass real bad (bus error) - strtok is defined
as char *strtok(char *, const char *) - what''s going on?

more craziness: if I declare/initialise

char *str;
str = strdup("dot.delimited.str)

inside tokconvert (instead of main) and pass that to strtok - it runs
fine!!

any thoughts are most welcome..

chumbo.

P.S.
btw this is on FreeBSD 5.1.2 (using gcc 3.3.3)

解决方案

Chumbo wrote:

the thing compiles and runs fine, however if I declare char *str =
"dot.delimited.str" (instead of char str[] = "dot.delimited.str") the
whole thing falls on its ass real bad (bus error) - strtok is defined
as char *strtok(char *, const char *) - what''s going on?



char *str = "blah";

is allowed to be placed in read-only memory. The data cannot be modified.

char str[], however, must be placed in memory modifiable by you (i.e. the
stack).

--
Jason Whitehurst


Jason Whitehurst wrote:

is allowed to be placed in read-only memory. The data cannot be
modified.



Err, and in case you don''t know, strtok(3) modifies the input string. Thus,
your problem.

--
Jason Whitehurst


In article <50**************************@posting.google.com >,
Chumbo <ch*********@hotmail.com> wrote:

If I have this(please bear with me - this is a case of a former java
guy going back to C ;-)

int main () {
char *tokconvert(char*);
It will confuse people less if you put function prototypes at file scope
instead of inside functions. (In this particular case, you can avoid
needing the prototype altogether by putting tokconvert before main(),
but that''s not always possible or reasonable.)
char str[] = "dot.delimited.str";
This allocates an array of char and populates it with the characters
in the string "dot.delimited.str" (including the terminating ''\0'').
The array is in the automatic-allocation space (we can call this "the
stack", but we prefer not to, because the function-invocation stack that
it exists in is not the same stack as the "processor''s stack segment"
stack (which need not even exist) that people typically assume we''re
talking about), and therefore that we can do pretty much whatever we
want with it (the relevant bit of that here is that we can write to it)
until the function returns.
char *result;

result = tokconvert(str);
When you pass str (an array) to a function (or do most other things with
it, notable exceptions being applying & or sizeof to it), the array name
decays to a pointer to the array''s first element. In this case, this
is exactly what you want - a pointer to the first character of the string.
return 0;
}

char *tokconvert(char *strToConvert) {

char *token;
char *tokDelim =",.";

token=strtok(strToConvert, tokDelim);

while(token != NULL) {
printf("Token -> %s \n", token);
token=strtok(NULL, tokDelim);
}
You''re not returning anything here. Your compiler should have warned
you about that.
(I''m not sure what you''d''ve wanted to return; possibly this is a leftover
from doing something with the tokens other than just printing them?)
}
the thing compiles and runs fine, however if I declare char *str =
"dot.delimited.str" (instead of char str[] = "dot.delimited.str") the
whole thing falls on its ass real bad (bus error) - strtok is defined
as char *strtok(char *, const char *) - what''s going on?
When you say `char *str="a string literal"'', the string literal (like
any other string literal in the program[1]) refers to an anonymous
not-const-but-not-writeable array of characters containing the string.
In English, that means you''re allowed to point a pointer that you''re
allowed to write through at it (remember, arrays decay to pointers),
but you''re not actually allowed to write to it.

So, you have a pointer pointing at a string literal that you''re not
allowed to write to... and then you try to write to it (indirectly,
by passing it to strtok, which writes to its first argument). That''s
what''s causing your problem. The solution is to Don''t Do That, Then:
Allocate writeable space for the string you give strtok as its first
argument, either as an automatic variable (like in your code above)
or as dynamically allocated memory (f''rexample, memory from strdup as
below), and put the string into that.

more craziness: if I declare/initialise

char *str;
str = strdup("dot.delimited.str)

inside tokconvert (instead of main) and pass that to strtok - it runs
fine!!
Note that strdup is a unixism and not part of the C language.[2]

What strdup does is allocate (with malloc) enough memory to hold the
string you give it, and copy the string into that memory, and return a
pointer to the copy of the string. This memory is writeable, so giving
strdup a pointer to it isn''t a problem, for the same reason that giving
it a pointer to the automatically allocated array isn''t a problem.

P.S.
btw this is on FreeBSD 5.1.2 (using gcc 3.3.3)



If I''d needed to know that, then your question would have been
inappropriate for comp.lang.c and would have been better off asked in
a FreeBSD or GCC newsgroup.

But given that you''re using GCC: If you''d compiled with:
gcc -W -Wall -ansi -pedantic -O myprog.c
then GCC would have warned you about failing to return a value from
tokconvert, along with a bunch of other warnings about things that you
typically don''t want to do. This makes debugging some problems a lot
easier - they go away when the compiler stops warning you about them.
dave

[1] In language-lawyer-ese, the string in the array initialization
`char buf[]="a string"'' is an initializer, not a string literal;
this is, as far as I know, the only place you can have a string in
the source code that doesn''t represent an anonymous array of char.

[2] It''s in the implementation''s namespace, though, which means you''re
not allowed to define it yourself. The solution in comp.lang.c is
to use my_strdup, which can portably be defined and have the same
behavior as the unix strdup; the usual solution outside comp.lang.c
is to use the library''s strdup if it exists, and otherwise to apply
knowledge beyond that found in the language definition to establish
that the programmer is allowed to define a function by that name on
that implementation and do so.

--
Dave Vandervies dj******@csclub.uwaterloo.ca
Well, it''s rare. The usual reaction to "let me just show you the bit..."
is "Rich! Rich! We ***believe*** you, okay?!?!?!?!?!"
--Richard Heathfield in comp.lang.c


这篇关于疯狂的事情的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆