pointer from integer?


Z

Zach

I open a file and read each line, want to use strtok() to tokenize it:

(code snippets)

char tokenlist[2] = {':',' '};

char *p1, *p2;
unsigned int i;

for(i=0; i <= sizeof(tokenlist[2]); i++){

p1 = strtok(line,tokenlist);
printf("token 1: %s\n",p1);

p2 = strtok(NULL,tokenlist[i+1]);
printf("token 2: %s\n",p2);
}

when i compile i get the warning:

newmain4.c: In function ‘main’:
newmain4.c:65: warning: passing argument 2 of ‘strtok’ makes pointer
from integer without a cast
newmain4.c:68: warning: passing argument 2 of ‘strtok’ makes pointer
from integer without a cast

lines 65 and 68 are my strtok calls.

strtok returns a pointer value of type (char *), p1 and p2 are
pointers of type (char *) so what is the problem?

I ran it in gdb but it did not give a very detailed message. Just
mentioned strtok:

[email protected]:~/myprojects/netrek-log-parser$ gdb --args ./newmain4
test.log
GNU gdb 6.4.90-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db
library "/lib/tls/i686/cmov/libthread_db.so.1".

(gdb) run
Starting program: /afs/club.cc.cmu.edu/usr/chaos/myprojects/netrek-log-
parser/newmain4 test.logToken 0: :
Token 1:
Entering fgets while loop...
hello hello hello


Program received signal SIGSEGV, Segmentation fault.
0xb7ef8c44 in strtok () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt full
#0 0xb7ef8c44 in strtok () from /lib/tls/i686/cmov/libc.so.6
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
(gdb) quit
The program is running. Exit anyway? (y or n) y

Is there a way to get gdb to give more detailed output?

Zach
 
Ad

Advertisements

I

Ian Collins

Zach said:
I open a file and read each line, want to use strtok() to tokenize it:

(code snippets)

char tokenlist[2] = {':',' '};

char *p1, *p2;
unsigned int i;

for(i=0; i <= sizeof(tokenlist[2]); i++){

p1 = strtok(line,tokenlist);


The second parameter of strtok() is a const char*, you are passing it a
char.
 
M

Martin Ambuhl

Zach wrote:
[...]
char tokenlist[2] = {':',' '}; [...]
p1 = strtok(line,tokenlist);


This is a severe error. strtok() takes a pointer to char (pointing to a
zero-terminated char array, a string) as its second argument.
tokenlist is a char.

If you had had
char *tokenlist[2] = {":", " "};
then tokenlist would have been of the right type.

Since strtok() is destructive of its first argument, it is subject to
abuse and many programmers avoid it. I am not one of those who avoid
it, but I would never recommend its use to anyone who fails to get the
argument typr right, since that suggests an inattention to detail which
is not compatible with the safe use of strtok().
 
C

CBFalconer

Martin said:
Zach wrote:
[...]
char tokenlist[2] = {':',' '}; [...]
p1 = strtok(line,tokenlist);


This is a severe error. strtok() takes a pointer to char
(pointing to a zero-terminated char array, a string) as its
second argument. tokenlist is a char.

If you had had
char *tokenlist[2] = {":", " "};
then tokenlist would have been of the right type.

Since strtok() is destructive of its first argument, it is subject to
abuse and many programmers avoid it. I am not one of those who avoid
it, but I would never recommend its use to anyone who fails to get the
argument typr right, since that suggests an inattention to detail which
is not compatible with the safe use of strtok().


I suggest the OP consider using tknsplit. Use a define of TESTING
to include the testing code. The source follows:

/* ------- file tknsplit.h ----------*/
#ifndef H_tknsplit_h
# define H_tknsplit_h

# ifdef __cplusplus
extern "C" {
# endif

#include <stddef.h>

/* copy over the next tkn from an input string, after
skipping leading blanks (or other whitespace?). The
tkn is terminated by the first appearance of tknchar,
or by the end of the source string.

The caller must supply sufficient space in tkn to
receive any tkn, Otherwise tkns will be truncated.

Returns: a pointer past the terminating tknchar.

This will happily return an infinity of empty tkns if
called with src pointing to the end of a string. Tokens
will never include a copy of tknchar.

released to Public Domain, by C.B. Falconer.
Published 2006-02-20. Attribution appreciated.
revised 2007-05-26 (name)
*/

const char *tknsplit(const char *src, /* Source of tkns */
char tknchar, /* tkn delimiting char */
char *tkn, /* receiver of parsed tkn */
size_t lgh); /* length tkn can receive */
/* not including final '\0' */

# ifdef __cplusplus
}
# endif
#endif
/* ------- end file tknsplit.h ---------- */


/* --------- file tknsplit.c ---------- */
#include "tknsplit.h"

/* copy over the next tkn from an input string, after
skipping leading blanks (or other whitespace?). The
tkn is terminated by the first appearance of tknchar,
or by the end of the source string.

The caller must supply sufficient space in tkn to
receive any tkn, Otherwise tkns will be truncated.

Returns: a pointer past the terminating tknchar.

This will happily return an infinity of empty tkns if
called with src pointing to the end of a string. Tokens
will never include a copy of tknchar.

A better name would be "strtkn", except that is reserved
for the system namespace. Change to that at your risk.

released to Public Domain, by C.B. Falconer.
Published 2006-02-20. Attribution appreciated.
Revised 2006-06-13 2007-05-26 (name)
*/

const char *tknsplit(const char *src, /* Source of tkns */
char tknchar, /* tkn delimiting char */
char *tkn, /* receiver of parsed tkn */
size_t lgh) /* length tkn can receive */
/* not including final '\0' */
{
if (src) {
while (' ' == *src) src++;

while (*src && (tknchar != *src)) {
if (lgh) {
*tkn++ = *src;
--lgh;
}
src++;
}
if (*src && (tknchar == *src)) src++;
}
*tkn = '\0';
return src;
} /* tknsplit */

#ifdef TESTING
#include <stdio.h>

#define ABRsize 6 /* length of acceptable tkn abbreviations */

/* ---------------- */

static void showtkn(int i, char *tok)
{
putchar(i + '1'); putchar(':');
puts(tok);
} /* showtkn */

/* ---------------- */

int main(void)
{
char teststring[] = "This is a test, ,, abbrev, more";

const char *t, *s = teststring;
int i;
char tkn[ABRsize + 1];

puts(teststring);
t = s;
for (i = 0; i < 4; i++) {
t = tknsplit(t, ',', tkn, ABRsize);
showtkn(i, tkn);
}

puts("\nHow to detect 'no more tkns' while truncating");
t = s; i = 0;
while (*t) {
t = tknsplit(t, ',', tkn, 3);
showtkn(i, tkn);
i++;
}

puts("\nUsing blanks as tkn delimiters");
t = s; i = 0;
while (*t) {
t = tknsplit(t, ' ', tkn, ABRsize);
showtkn(i, tkn);
i++;
}
return 0;
} /* main */

#endif
/* ------- end file tknsplit.c ------- */
 
Ad

Advertisements

B

Barry Schwarz

I open a file and read each line, want to use strtok() to tokenize it:

(code snippets)

char tokenlist[2] = {':',' '};

If you want strtok to consider both ':' and ' ' as separators, then
you want
char tokenlist[] = ": ";
char *p1, *p2;
unsigned int i;

for(i=0; i <= sizeof(tokenlist[2]); i++){

tokenlist[2] is a non-existent object. However, since sizeof does not
evaluate its operand, the expression probably has type char and
sizeof(char) is always 1. This is an unfortunate coincidence since
your loop would execute twice which happens to be the correct number
of iterations.
p1 = strtok(line,tokenlist);


You need to research strtok in your reference. Neither tokenlist
or tokenlist are suitable arguments. The first has the wrong type and
the second does not point to a string.
printf("token 1: %s\n",p1);

p2 = strtok(NULL,tokenlist[i+1]);

When i is equal to 1 you attempt to evaluate tokenlist[2] which
invokes undefined behavior.
printf("token 2: %s\n",p2);
}

when i compile i get the warning:

newmain4.c: In function ‘main’:
newmain4.c:65: warning: passing argument 2 of ‘strtok’ makes pointer
from integer without a cast
newmain4.c:68: warning: passing argument 2 of ‘strtok’ makes pointer
from integer without a cast

What is the type of tokenlist? What type does strtok expect?
lines 65 and 68 are my strtok calls.

strtok returns a pointer value of type (char *), p1 and p2 are
pointers of type (char *) so what is the problem?

The message did not say you tried to do something wrong with a char*.
It said you tried to do something wrong with an integer.

snip
Program received signal SIGSEGV, Segmentation fault.
0xb7ef8c44 in strtok () from /lib/tls/i686/cmov/libc.so.6

Why on earth did you attempt to execute a program that did not compile
cleanly?
(gdb) bt full
#0 0xb7ef8c44 in strtok () from /lib/tls/i686/cmov/libc.so.6
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
(gdb) quit
The program is running. Exit anyway? (y or n) y

Is there a way to get gdb to give more detailed output?

That you need to ask in a group that deals with gdb.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top