views:

91

answers:

2

Hey! I'm fixing a program but I'm facing a problem and I cant really realize what's the wrong on the code. I would appreciate any help. I didnt post all the code...but i think with this part you can get an idea of it. With the following function enter() I wanna add user commands' datas to a list. eg. user give the command: "en james bond 007 gun" ["en" means "enter" on command prompt]

'james' is supposed to be the name, 'bond' the surname, 007 the amount and the rest is the description. I use strtok in order to 'cut' the command,then i put each name on a temp array. Then i call InsertSort in order to put the datas on a linked list but in alphabetical order depending on the surname that users give. I wanna keep the list on order and put each time the elements on the right position.

Also,maybe there is a fault on InsertSort() and SortedInsert()...as datas aren't written on the list as they ought to.

/* struct for all the datas that user enters on file*/
typedef struct catalog    
{
       char short_name[50];                    
       char surname[50];                       
       signed int amount;                      
       char description[1000];              

       struct catalog *next;

}catalog,*catalogPointer;   

catalogPointer current;
catalogPointer head = NULL; 

void enter(void)//user command: en <name> <surname> <amount> <description>
{ int n,j=2,k=0;
 char temp[1500];
    char command[1500];

 while (command[j]!=' ' && command[j]!='\0') 
 { temp[k]=command[j];    
  j++;      
  k++;      
 }
 temp[k]='\0';      

 char *curToken = strtok(temp," ");   
 printf("temp is:%s \n",temp);

 char short_name[50],surname[50],description[1000];
 signed int amount;
 //short_name=(char *)malloc(sizeof (char *));
 //surname=(char *)malloc(sizeof (char *));
 //description=(char *)malloc(sizeof (char *));
 //amount=(int *)malloc(sizeof (int *));
 printf("\nWhat you entered for saving:\n");
 for (n = 0; curToken !='\0'; ++n)   
 { 
  if (curToken)
  { 
    strncpy(short_name, curToken, sizeof (char *)); /
  } 
  printf("Short Name: %s \n",short_name);    

  curToken = strtok(NULL," ");      
  if (curToken)
     strncpy(surname, curToken, sizeof (char *)); /
  printf("SurName: %s \n",surname);

  curToken = strtok(NULL," ");      
  if (curToken)
  {
     char *chk;     
     amount = (int) strtol(curToken, &chk, 10); 
    if (!isspace(*chk) && *chk != 0)
                    fprintf(stderr,"Warning: expected integer value for amount, received %s instead\n",curToken);
  }
  printf("Amount: %d \n",amount);
  curToken = strtok(NULL,"\0");     
  if (curToken)
    { strncpy(description, curToken, sizeof (char *));   
  }
  printf("Description: %s \n",description);
  break;
 }

 if (findEntryExists(head, surname) != NULL)
  printf("\nAn entry for <%s %s> is already in the catalog!\nNew entry not entered.\n",short_name,surname);
 else
 {
  printf("\nTry to entry <%s %s %d %s> in the catalog list!\n",short_name,surname,amount,description);
  InsertSort(&head,short_name, surname, amount, description);
  printf("\n**Entry done!**\n");
 }
 // Maintain the list in alphabetical order by surname.


}


/********Uses special case code for the head end********/
void SortedInsert(catalog** headRef, catalogPointer newNode,char short_name[],char surname[],signed int amount,char description[])
{
 strcpy(newNode->short_name, short_name);   
 strcpy(newNode->surname, surname);
 newNode->amount=amount;
 strcpy(newNode->description, description);

 // Special case for the head end
 if (*headRef == NULL||(*headRef)->surname >= newNode->surname)  
 {  newNode->next = *headRef;    
        *headRef = newNode;     
    }
    else 
 {       // Locate the node before the point of insertion
       catalogPointer current = *headRef;   
  catalogPointer temp=current->next;  
       while ( temp!=NULL )  
  {  
       if(strcmp(temp->surname,newNode->surname)<0 ) 
               current = temp; 
       }
       newNode->next = temp;    
       temp = newNode;    
    }
}


// Given a list, change it to be in sorted order (using SortedInsert()).
void InsertSort(catalog** headRef,char short_name[],char surname[],signed int amount,char description[])
{
 catalogPointer result = NULL;         // build the answer here
    catalogPointer current = *headRef;   // iterate over the original list
    catalogPointer next;     
    while (current!=NULL) 
 {
      next = current->next;    // tricky - note the next pointer before we change it
      SortedInsert(&result,current,short_name,surname,amount,description);
      current = next;
    } 
    *headRef = result;
}

Running the program I get these strange things (garbage?)...

Choose your selection:

en james bond 007 gun

Your command is: en james bond 007 gun

temp is:james

What you entered for saving: Short

Name: james
SurName:
Amount: 0

Description: 0T�Г

Try to entry james 0 0T�Г in the catalog list!

Entry done!

Also I'm facing a problem on how to use the 'malloc' on this program.

Thanks in advance. . .

UPDATE: I made an other fuction for entry. But somehow strange i get segmentation for strcpy!!!! That's it:

catalogPointer newEntry (char short_name[], char surname[], signed int amount, char description[])
{ 
 catalogPointer newNode,first,second,tmp;
 first=head;
 second=NULL;
 strcpy(newNode->short_name, short_name); //SEGMENTATION
    strcpy(newNode->surname, surname);
    newNode->amount=amount;
    strcpy(newNode->description, description);

 while (first!=NULL)      
 {     if (strcmp(surname,first->surname)>0)
   second=first;
  else if (strcmp(surname,first->surname)==0)
       {
      if (strcmp(short_name,first->short_name)>0)
   second=first;
  }
  first=first->next;
 }
 if (second==NULL)
 {     newNode->next=head;
  head=newNode;
 }
 else
 {      tmp=second->next;
           newNode->next=tmp;
           first->next=newNode;
 }

}

+3  A: 

Solution

The direct reason of your problem is here:

while (command[j]!=' ' && command[j]!='\0') 
 { temp[k]=command[j];    
  j++;      
  k++;      
 }

What you are doing here is copying the contents of command into temp until the first space character. That is, you only copy "james". Thus after the short name, there is nothing more for strtok to parse, so the other buffers don't get initialized properly and contain only garbage.

Update: To copy stuff after the first space character, use strchr and strcpy instead of that loop:

char* params = strchr(command, ' ') + 1;
strcpy(temp, params);

Other observations

Apart from this, you give the size of the destination buffer incorrectly here:

strncpy(surname, curToken, sizeof (char *));

should be

strncpy(surname, curToken, 49);

Secondly: the loop expression in

for (n = 0; curToken !='\0'; ++n)   

should be

for (n = 0; curToken; ++n)   

otherwise the loop will not terminate correctly when all tokens have been parsed.

Péter Török
@Peter Torok: 1st observation:maybe that's right...but i just left it like that 'cause i wanna use after malloc...anyway that one didn't change anything on the running! :( –2nd observation: i checked it, that also doesn't affect anything!
FILIaS
@Peter Torok: But how strcpy will 'cut' the elements on each whitespace?
FILIaS
@FILIaS, it is not supposed to cut anything, just copy the whole command into temp - `strtok` will cut the elements.
Péter Török
@Peter Torok:Yes but i used this while in order temp to dont contain 'en' (enter) but only the rest of it (eg command: en james bond 7 gun temp:james bond 7 gun) temp is there in order to keep the command but without the first 2 letters (used to be on menu selection)
FILIaS
@Peter Torok: For update: Thank you! That's it! I always forget about strchr! Thaanxx
FILIaS
@FILIaS, actually an even simpler solution is to tokenize the command string as is and simply omit the first token...
Péter Török
@Peter Torok: Why is this '+1' there? for null?
FILIaS
@FILIaS, `strchr` returns a pointer to the first space within the command. You want a pointer to the char right _after_ that space.
Péter Török
@FILIaS, `strtok(temp," "); curToken = strtok(NULL," ");`
Péter Török
Thank you Peter Torok! Please as you 're still here,could you propose me a way to use malloc? I have given maximum number to strings...but i wanna save as much memory as each name of the user is.
FILIaS
@FILIaS, e.g. `char* short_name = malloc(strlen(curToken) + 1);`
Péter Török
@FILIaS, just as a reminder, your accept rate is rather low, so don't forget to click on the accept mark :-) In fact, consider going back to your previous questions and accept applicable answers...
Péter Török
@Peter Torok. when i get acceptable answers I click on the mark ;) Until now only on 2 questions i've get one!
FILIaS
@Peter Torok, except these do you maybe observe any other fault on the rest code? Because the datas arent written on the list :((
FILIaS
@FILIaS, apparently you start with an empty list (`head` is initialized to NULL) and `InsertSort` doesn't handle empty lists properly. Moreover, it seems to me that in a nonempty list, all elements will be overwritten with the new data. Moreover in `SortedInsert`, `(*headRef)->surname >= newNode->surname` will not compare two strings, but two pointers - use `strcmp` instead.
Péter Török
@Peter. see the update post
FILIaS
@FILIaS, `newNode` is not initialized. IMHO you should not edit and modify your original question endlessly - this is already a different problem from your original, so you should post a new question.
Péter Török
@Peter.My problem was the entry function.That's why i posted there another version of it.Anyway, should i put newNode to null? :///
FILIaS
@FILIaS, that's what I mean. And you should [`malloc`](http://cplusplus.com/reference/clibrary/cstdlib/malloc/) the new node since you want to store something in it. I'm gonna leave soon so I won't be checking SO much further. Post a new question if you still have problems.
Péter Török
@Peter Torok. it just needed malloc without initialization. thanx
FILIaS
+2  A: 

You don't seem to be filling command with anything, so you are tokenising whatever garbage was on the stack.

Pete Kirkham
@Pete Kirkham: Yes that seems to be.But how then can I take the command? and each word between spaces?
FILIaS
well, where should the command come from? a disk file, a database, console input, gui? either read it in somewhere, and pass it as a parameter, or read it in in your function.
Pete Kirkham
@Pete Kirkham. command comes from user,from console input. That's solved.Thanks to Peter Torok.
FILIaS