Hi guys, I've got troubles with a conversion.
My function:
void stringFormat (char *input, int nums)
receives a string like this:
"name;3,45,5,6,77;"
and a number indicating how many numbers in the String (in this case 5)
I've got to tokenize the string in order to obtain:
1) a string named data: "name"
2) an array of int made of the numbers received: numbers[0]=3; numbers[1]=45; and so on 'til 77
Here's my wrong solution:

void stringFormat(char *input, int nums){
	
	char *data;
	int *numbers[nums];
	int i=0;		
	char *p;
	
	p = strtok (input,";");
	if(p != NULL) data=p;
	
	p = strtok (NULL, ",;");
  	while (p != NULL)
  	{
  	  numbers[i] = p;
	  i++; 
	  p = strtok (NULL, ",;");
 	}
	
	i=0;

        /* I check array content  */
	while (i<(nums)){
		printf("%d\n", *(numbers[i]) );
		i++;
	}
}

...any suggestion will be highly appreciated !!

Member Avatar for iamthwee

>int *numbers[nums];

Doesn't that have to be like... a static value? It may be ok I dunno, If you wanna do that dynamically maybe you need malloc or something? Or you could just initialise it to be a really big value, but that's not cast iron...

Hi guys, I've got troubles with a conversion.

int *numbers[nums];  /* this is an array of pointers of type int */
      
    char *p; /* this is a pointer to a string */
    
     numbers[i] = p; /* You are trying to assign a string to an element of the array of pointers type int */

That doesn't work. You need to convert the number value store in the string pointed by `p' into integer before storing in numbers.
Maybe use sscanf() to read the value from the string.

Member Avatar for iamthwee

>int *numbers[nums];

Doesn't that have to be like... a static value? It may be ok I dunno, If you wanna do that dynamically maybe you need malloc or something? Or you could just initialise it to be a really big value, but that's not cast iron...

Um actually that may be wrong...I could have sworn I remembered something like that not working...lolz

#include <stdio.h>
#include <string.h>
 
void stringFormat ( int nums );
 
int main ( void )
{
  stringFormat ( 143 ); /*test*/
  getchar();
  return 0;
}
void stringFormat ( int nums )
{
  int numbers[nums];
  int i;
  for ( i = 0; i < nums; i++ )
  {
    numbers[i] = 1;
    printf ( "%d", numbers[i] );
  }
}

Anyway, have a look at some daniweb tutorials which you should find useful.

http://www.daniweb.com/code/coder5020-timestamp-2.html
http://www.daniweb.com/tutorials/tutorial45806.html

Um actually that may be wrong...I could have sworn I remembered something like that not working...lolz

#include <stdio.h>
#include <string.h>
 
void stringFormat ( int nums );
 (...)

Your code works correctly on my PC, maybe assigning a variable instead of a static value it's only bad style since I get "only" a gcc warning.
Anyway, even if I iniitialise it with a big value the problem persists.

int *numbers[nums];  /* this is an array of pointers of type int */
      
    char *p; /* this is a pointer to a string */
    
     numbers[i] = p; /* You are trying to assign a string to an element of the array of pointers type int */

That doesn't work. You need to convert the number value store in the string pointed by `p' into integer before storing in numbers.
Maybe use sscanf() to read the value from the string.

You guessed the core of the problem.
I've seen some sscanf() tutorials but I've not understood the difference with strtok().
In my case, there's no way to perform a "on the fly" conversion using i.e. atoi()
something like:
numbers = atoi(p);
dunno why it doesn't work!
ps: my variable numbers it's a pointer to an array of int, maybe I missed a couple of parenteses so it looked like an array of pointers of type int..

Member Avatar for iamthwee

Did you look at those links?

Did you look at those links?

Yes I read something and put the rest in bookmarks, but I've not found my answer.
I'd like to know why my code doesn't work with strtok() and atoi(), before changing everything and using sscanf() (which I found a little tricky..)

Member Avatar for iamthwee

No idea, I don't have a compiler to test so this is from my head.

It doesn't put it into an array but that's should be trivial. Maybe it will give you hints?

#include <stdio.h>
#include <string.h>
int main ()
{
  char str[] ="retard;3,4510,-5,6,77;";
  char * pch;
  printf ("Splitting: %s",str);
  printf("\n");
  pch = strtok (str,",;");
 
  int count = 0;
  char data[BUFSIZ];
  while (pch != NULL)
  {
     char buf[BUFSIZ];
     char *p;
     printf ("%s ",pch);
 
    int i = strtol(pch, &p, 10);
 
    if (pch[0] != '\n' && (*p == '\n' || *p == '\0'))
    {
      printf (" = Valid integer %d entered\n", i);
      /*Add this to your integer array*/
    }
    else
    {
      printf(" = This is string not an integer\n");
      strcpy(data,pch);
    }
 
     pch = strtok (NULL, ",;");
     count++;  
  }
 
  printf("The string named Data is \"%s\" ",data);
 
  getchar();
  return 0;
}

You guessed the core of the problem.
I've seen some sscanf() tutorials but I've not understood the difference with strtok().
In my case, there's no way to perform a "on the fly" conversion using i.e. atoi()
something like:
numbers = atoi(p);
dunno why it doesn't work!
ps: my variable numbers it's a pointer to an array of int, maybe I missed a couple of parenteses so it looked like an array of pointers of type int..

Here's the changes for your code to work using sscanf() to read the integer.

int numbers[nums]; /* this needs to be an array of integers */
    .
    .
    .
     while (p != NULL)
     {
        sscanf(p, "%d", &numbers[i]); /* scan string for an integer */
        ++i; 
        p = strtok (NULL, ",;");
     }

numbers = atoi(p);
dunno why it doesn't work!

You need to make numbers an array of integers and not an array of pointers of type int. Right now you are trying to assign whatever atoi(p) gives you to a pointer memory which it can only hold the address of another memory and not an integer value.

Many thanks! I decided to use strtok() for data and sscanf for numbers, and with some arrangments from the two codes you posted I managed to fix the problem: it seems to work properly.

Unfortunately now I'm discovering that even my string management it's not so good.
I've a problem in recognizing a char array, when I test it with ==.
Let me explain the question with an easy example I've written:

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

int main() {

  char *string;
  char temp[4];

  string = "Bye";

  temp[0]='B';
  temp[1]='y';
  temp[2]='e';
  temp[3]='\0';
    
  compare(string);
  compare(temp);

  return 0;
}



void compare(char* input){

	char *local = "Bye";

	if(local == input) printf("Recognized as equal!\n");
	else printf("Recognized as different!\n");
}

Obviously string is recognized as equal, temp it's not.
At first I thought it was because of the lack of '\0' but in the example I've added it with no results....
I'd like to make temp be recognized as equal to local. Is there some tricks I can use in main without changing the funcion compare() adopting strcmp()?

If you want to compare two strings, then you have to use strcmp().

> Obviously string is recognized as equal, temp it's not.
That is more down to accident, rather than design.

A "string" is a constant in many C implementations, which means that the compiler is allowed to take every occurrence of say "bye" and make them all refer to just ONE instance of the string. This potentially saves a lot of space. A side effect of this is that if you try to compare them with just the pointers, they will compare equal (in the same way that &var == &var, for any given variable).

So saying if ( "Bye" == "Bye" ) is really down to whether your compiler chooses to perform string constant merging (or not). If it seems to 'work', then it has nothing to do with the code being correct.

-fwritable-strings
Store string constants in the writable data segment and don't uniquize them. This is for compatibility with old programs which assume they can write into string constants.

Writing into string constants is a very bad idea; “constants” should be constant.

This option is deprecated.

gcc4.x removes this option altogether.

Member Avatar for iamthwee

Yes you can't compare strings with == . Use strcmp() as mentioned. Perhaps you might want to peruse this

>Many thanks! I decided to use strtok() for data and sscanf for numbers, and with some arrangments from the two codes you posted I managed to fix the problem

Please can you post your complete solution for the benefit of the community and so others can check over...

Obviously string is recognized as equal, temp it's not.
At first I thought it was because of the lack of '\0' but in the example

if(local == input) compares the value of pointer local which is a memory location against the value of pointer input which could be the same memory location or another one.

Maybe this modification to your code throw some light to the matter; take a look at the extra printf() and at the memories addresses in the output :

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

void compare(char* input);

int main() {

  char *string;
  char temp[4];

  string = "Bye";

  temp[0]='B';
  temp[1]='y';
  temp[2]='e';
  temp[3]='\0';
    
  compare(string);
  compare(temp);

  return 0;
}



void compare(char* input){

    char *local = "Bye";

    if(local == input) printf("\nRecognized as equal!\n\n");
    else printf("\nRecognized as different!\n\n");

    /* display what local is pointing to */
    printf ("pointer local says \"%s\"\n", local);

    /* display what input is pointing to */
    printf ("pointer input says \"%s\"\n", input);

    /* display the value these two pointers hold in storage */
    printf ("Memory address value store in pointer `input\' = %p\n", input);
    printf ("Memory address value store in pointer `local\' = %p\n\n", local);

}

/* output:
Recognized as equal!
pointer local says "Bye"
pointer input says "Bye"
Memory address value store in pointer `input' = 00403000
Memory address value store in pointer `local' = 00403000

Recognized as different!
pointer local says "Bye"
pointer input says "Bye"
Memory address value store in pointer `input' = 0022FF70
Memory address value store in pointer `local' = 00403000
*/

Many thanks for your indeepth replies, I think I've clearly understood this point, very interesting the example and the link to the faq, it seems it was there just for me!
As requested, I post my final solution to the matter:

void stringFormat(char *input, int nums){
  char *data;
  int numbers[nums];
  int i=0;		
  char *p;
	
  p = strtok (input,";");
  if(p != NULL) data = p;
  
  p = strtok (NULL, ",;");
  while (p != NULL){
	sscanf(p, "%d", numbers[i]);
	i++;
	p = strtok (NULL, ",;");
  }
}

It seems to work properly, but if something is not good style, or can be strengthened, any inputs are obviously welcome!

> int numbers[nums];
C89 doesn't allow variable length arrays, this was added to C99.

> sscanf(p, "%d", numbers);
I'm surprised it "worked properly" since you forgot the &
Further, if you want to make sure the user didn't enter "123,abc,456", then you should check the result returned by sscanf().
For extra points, use strtol(), which further enhances error detection by detecting numeric overflow.

> int numbers[nums];
C89 doesn't allow variable length arrays, this was added to C99.

Yes, gcc says that, better if I fix it using a constant inside the function? I don't know other ways to solve this issue...

> sscanf(p, "%d", numbers);
I'm surprised it "worked properly" since you forgot the &
Further, if you want to make sure the user didn't enter "123,abc,456", then you should check the result returned by sscanf().
For extra points, use strtol(), which further enhances error detection by detecting numeric overflow.

I've not checked the result returned by sscanf() 'cause the string is automatically made by another function where I do error checking.
I forgot the & because my code was slightly different, I used a pointer to an array, and in writing here I forgot it, now it seems I can't edit the code anymore...

> better if I fix it using a constant inside the function?
Since you're presently scanning the line, then throwing the results away, it might be better to pass a pointer to the int array where you want the results stored.

> now it seems I can't edit the code anymore...
What's that supposed to mean - somebody steal your keyboard?

> I forgot the & because my code was slightly different
If you don't post what you actually tried, then expect long threads and annoyed helpers.
Programming languages do not tolerate vague "well it was something like this". There are many places where being off by just 1 character can radically alter the behaviour of a program. If, in your attempt to approximate the question, you omit this, then anything you get back is meaningless (and a waste of time).

>>There are many places where being off by just 1 character can radically alter the behaviour of a program
OMG its sooo true, I've had that happen all too often.

Member Avatar for iamthwee

> now it seems I can't edit the code anymore...
What's that supposed to mean - somebody steal your keyboard?

I think he/she meant due to the time constraint on editting the 'Daniweb posts' they were unable to change their code.

I think he/she meant due to the time constraint on editting the 'Daniweb posts' they were unable to change their code.

Yes, here's the problem, I'm sorry for that.
Anyway the code is very well working, the only thing I changed after all it's the pointer to the array because further operations that I had to do in the program required that, so I had to change it consistently...
If any mod reads it and is in the mood to change my code adding the & I would be very grateful.
Many thanks to you all, you really helped me, I'm marking this thread as solved!

>If any mod reads it and is in the mood to change my code adding the & I would be very grateful.
It's generally better to leave the code as you originally posted it so that any replies remain relevant. If you have a new version of the code, create a new post in the thread with the updated source.

Good idea, Narue...
Here's the updated version, with the pointer issue fixed!

void stringFormat(char *input, int nums){
  char *data;
  int numbers[nums];
  int i=0;		
  char *p;
	
  p = strtok (input,";");
  if(p != NULL) data = p;
  
  p = strtok (NULL, ",;");
  while (p != NULL){
	sscanf(p, "%d", &numbers[i]);
	i++;
	p = strtok (NULL, ",;");
  }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.