Splitting up a string

This is a discussion on Splitting up a string within the C Programming forums, part of the General Programming Boards category; my input file will contain: ABC|DEF|91 XYZ|LDS|78 Output should be: First Name..........Last Name..........Grade ABC......................DEF...................... .91 XYZ......................LDS...................... .78 I am trying ...

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    33

    Talking Splitting up a string

    my input file will contain:


    ABC|DEF|91
    XYZ|LDS|78

    Output should be:

    First Name..........Last Name..........Grade
    ABC......................DEF...................... .91
    XYZ......................LDS...................... .78

    I am trying to get it to split at the '|' points.


    Question:

    I am trying to break this up into first name, last name, and grade. I have been able to get it to split the first name and grade and print those out, but getting it to split the 3rd time is giving me trouble.




    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct person{
           char name[30];
           int age;
           };
           int main(int args, char *argv[])
           {
                   struct person list[30];
                   int i,n;
                   char *ch,*ch1;
                   char buf[256];
                   FILE *fp;
    
                   fp = fopen(argv[1],"r");
                   if(fp == NULL){
                           printf("Cannot open file %s\n", argv[1]);
                           exit(0);
                           }
                   i=0;
                   fgets(buf,256,fp);
                   while(!feof(fp)){
                           ch = strchr(buf,'\n');
                           if(ch != NULL) *ch = '\0';
                           else break;
                           ch = strchr(buf,'|');
                           if(ch != NULL){
                                   *ch = '\0';ch1 = ++ch;
                                   }
                   else break;
                   strcpy(list[i].name,buf);
                   list[i].age = atoi(ch1);
                   i++;
                   fgets(buf,256,fp);
                   }
           n = i;
    
           for (i = 0; i < n; i++)
                   printf("%s is %d years old\n",list[i].name,list[i].age);
                   return 0;
                   
                   
          printf("
         
                   
                   
                   
    }
    In present form the current code will take:

    ABC|78
    XYZ|56

    and outprint:


    First Name.......................Last Name.......................Grade
    ABC...................................________.... ......................78
    XYZ...................................________.... ......................56



    So I feel like I'm pretty close. Anybody have ideas or pointers? THANKS!

  2. #2
    Registered User
    Join Date
    Feb 2010
    Posts
    36
    You try the following code.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct person{
            char firstname[30]; //array for storing the firstname 
            char lastname[30]; //array for storing the lastname
            int age; //age for storing the age of the person
    };
    int main(int args, char *argv[])
    {
            struct person list[30];
            int i,n;
            char *ch,*ch1,*ch2,*ch3; //declaring pointers to character
            char buf[256];
            FILE *fp;
    
            fp = fopen(argv[1],"r");
            if(fp == NULL){
                    printf("Cannot open file %s\n", argv[1]);
                    exit(0);
            }
            i=0;
            fgets(buf,256,fp);
            while(!feof(fp)){
                    ch = strchr(buf,'\n'); 
                    if(ch != NULL) *ch = '\0';
                    else break;
                    ch = strchr(buf,'|'); //searching for the character | in buf and returning the pointer if it matched
                    ch2 = strrchr(buf,'|'); //searching the pipe character from the end of the string and it returns the pointer
                    if(ch != NULL)
                    {
                            *ch = '\0';ch1 = ++ch2; //moving the end pointer one position to point to the age value instead of |
                    }
                    else break;
                    ch++; //moving the pointer to point to the first character of the last name after first name instead of | 
                    strcpy(ch3,ch); //copying the content lastname|age to ch3 string
                    ch2=strchr(ch3,'|'); //searching for the character | in the ch3 
                    *ch2='\0'; //making that position as null to print only the last name
                    strcpy(list[i].firstname,buf); //copying the first name from buffer to structure
                    strcpy(list[i].lastname,ch3); //copying the lasst name from buffer to structure
                    list[i].age = atoi(ch1); //storing the age into structure
                    i++;
                    fgets(buf,256,fp);
            }
            n = i;
    
            for (i = 0; i < n; i++)
                    printf("%s's last name %s and he is %d years old\n",list[i].firstname,list[i].lastname,list[i].age);
            return 0;
    }
    Last edited by vivekraj; 03-02-2010 at 10:00 PM. Reason: I have mentioned the comments for the statements what I have changed or added in your program.

  3. #3
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    Hey thanks a lot. Would you mind explaining what you added and what how it works or what it does?

  4. #4
    Registered User ungalnanban's Avatar
    Join Date
    Feb 2010
    Location
    Chenai
    Posts
    12

    Thumbs up

    Are you trying for this? See one more Example.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include<stdlib.h>
    #include<malloc.h>
    
    char *replace(char *str, char *old, char *new) {
      int i, count = 0;
      int new_len = strlen(new);
      int old_len = strlen(old);
    
      for (i = 0; str[i]; ++i)
        if (strstr(&str[i], old) == &str[i])
          ++count, i += old_len - 1;
    
      char *buffer = (char *) calloc(i + 1 + count * (new_len - old_len), sizeof(char));
      if (!buffer) return;
    
      i = 0;
      while (*str)
        if (strstr(str, old) == str)
          strcpy(&buffer[i], new),
          i += new_len,
          str += old_len;
        else
          buffer[i++] = *str++;
    
      buffer[i] = '\0';
      return buffer;
    }
    int main() {
    
                   FILE *fp;
                   char *buf;
    
                   fp = fopen("input_file","r");
                   int i=0;
                   buf=malloc(1056);
    
                   fread(buf,1056,1056,fp);
               buf = replace(buf, "|", "---");
               printf("%s",buf);
    
    }

  5. #5
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    thanks for the reply ungalnanban, but that isn't quite what i was looking for.

  6. #6
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    thanks vivekraj! I appreciate your time

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Just use strtok()
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  8. #8
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    Thanks guys for the help!!!

    Ok got another predicament.

    So here is the input in the form of lastname|firstname|grade:


    ABC|DEF|123


    so last name is ABC
    first name is DEF
    grade is 123


    I am wanting to check that every set has a last name and grade, they are allowed to not have a first name

    for example if i had input of:

    |DEF|123
    ABC|DEF|

    I want it to reject these and continue on to the next line. Ultimate goal is to write the "rejected" inputs to a file called rejected, but I can do that on my own. I just need help getting started with how to go about checking to make sure I have the required fields in my input file.
    Last edited by monki000; 03-03-2010 at 10:07 PM. Reason: Had a thought.....

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    I gather that you have already written the code to read from file into an array of struct person? You should modify that read process such that it checks that the last name and grade when read are not empty.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    ok....it goes through and pulls ABC and stores it in array ch3, then pulls DEF and stores it, and pulls 123 and stores it. Is there a way that I could check and see if nothing was stored? something like.....

    if (ch3 = '\0' ) can i do that? since it's an array. just say "if" it only contains \0 reject it.



    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct person{
            char firstname[30];
            char lastname[30];
            char grade;
            float age;
    };
    int main(int args, char *argv[])
    {
            struct person list[30];
            int i,n;
            char *ch,*ch1,*ch2,ch3[50],assignedGrade[1];
            char buf[256];
            FILE *fp;
    
            fp = fopen(argv[1],"r");
            if(fp == NULL){
                    printf("Cannot open file %s\n", argv[1]);
                    exit(0);
            }
            i=0;
            fgets(buf,256,fp);
            while(!feof(fp))
            {
                    ch = strchr(buf,'\n');
                    if(ch != NULL) *ch = '\0';
                    else break;
                    ch = strchr(buf,'|');
                    ch2 = strrchr(buf,'|');
                    if(ch != NULL)
                    {
                       *ch = '\0';ch1 = ++ch2;
                    }
                    else break;
                    ch++;
                    strcpy(ch3,ch);
                    ch2=strchr(ch3,'|');
                    *ch2='\0';
                    char grade; 
                    strcpy(list[i].firstname,buf);
                    strcpy(list[i].lastname,ch3);
                    list[i].age = atof(ch1);
                    int getGrade;
                    getGrade = atof(ch1);
                    
         switch ( getGrade/10) {
       	case 9:
       	assignedGrade[0] = 'A';
       	
       	break;
       	case 8:
       	assignedGrade[0] = 'B';
       	
       	break;
       	case 7:
       	assignedGrade[0] = 'C';
       	
       	break;
       	default:
       	assignedGrade[0] = 'F';
                   
        break;       
       }
       
        list[i].grade = assignedGrade[0]; 
        i++;
       fgets(buf,256,fp);
       
       
       
       
       
            }
            n = i;
           
            printf("Last Name  First Name  Grade  Letter Grade  \n");
            for (i = 0; i < n; i++)
            printf("%s        %s         %4.2f         %c\n",list[i].firstname,list[i].lastname,list[i].age, list[i].grade);
            return 0;
    }


    Part of this code is irrelevant to my question, but this is my code as it sits now. It compiles and runs. Just needed to add the step I talked about.
    Last edited by monki000; 03-03-2010 at 10:10 PM.

  11. #11
    Registered User
    Join Date
    Feb 2010
    Posts
    11
    Try the following algorithm for your additional requirement.

    Code:
    - Check the firstname whether it is a null.
    - Compare the current lastname with next record lastname .
    - The above 2 conditions are true , move that record to your target file.

  12. #12
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,452
    Code:
                   fgets(buf,256,fp);
                   while(!feof(fp)){
                      fgets(buf,256,fp);
                   }
    This you can simply replace with
    Code:
    while (  fgets(buf,sizeof buff,fp) != NULL ) {
    }

    @ungalnanban
    > buf=malloc(1056);
    > fread(buf,1056,1056,fp);
    1. Where did 1056 come from?
    2. fread would read up to 1056*1056 -> massive buffer overflow
    3. fread() does NOT append a \0, so the later string operations are broken.
    Plenty of other mistakes for the observant as well.



    Also, you need to work on your indentation. The code is all but unreadable posted on a forum.
    Check your IDE settings, and make sure it is set to "use spaces for tabs".
    Clever IDEs can make sense of mixed spaces and tabs, but HTML can't.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  13. #13
    Registered User
    Join Date
    Feb 2010
    Posts
    33
    First off, a really appreciate the help everyone has provided me! I have learned alot in the past few days. I believe I am VERY close to finishing this. One thing I lack is to sort the person(s) by last name. I added a swap function and a sort function, but am unsure where and how to call upon them. Any advice would be helpful, my code is as follows.

    Code:
    /*This program reads in a list of names, verifies their structure,
     * sorts them by last name, calculates their letter grade, and 
     * prints all relevant information in a sorted list*/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Assigns the structure of a person
    struct person{
            char firstName[30]; 
            char lastName[30]; 
            char grade;
            float points; 
    };
    // Swap function
    void swap(struct person *p1,struct person *p2)
    {
    	char z;
    	float x;
    	char temp[30];
    	char temp1[30];
    	strcpy(temp, p1->lastName);
    	strcpy(temp1, p1->firstName);
    	z = p1 -> grade;
    	x = p1 -> points;
    	strcpy(p1 ->lastName,p2->lastName);
    	strcpy(p1 ->firstName,p2->firstName);
    	p1 ->grade = p2->grade;
    	p1 ->points = p2->points;
    	strcpy(p2 ->lastName,temp);
    	strcpy(p2 ->firstName,temp);
    	p2->grade=z;
    	p2->points=x;
    }
    // Sort function	
    void psort(int n, struct person student[])
    	{
      	int i;
       	int j;
        for (i=0; i < n; i++)
            for (j=i+1; j<n; j++)
            if (strcmp(student[i].lastName,student[j].lastName) > 0)
        		swap(&student[i],&student[j]);
    }
    // Beginning of main
    int main(int args, char *argv[])
    {
            struct person student[30];
            int i,n,gradeCalculate;
            int a=0,b=0,c=0,d=0,f=0;
            char *ch,*ch1,*ch2;
            char ch3[10]; 
            char buf[256];
            FILE *fp;
            FILE *fp2;
    // Makes sure files and loads it to buf
            fp = fopen(argv[1],"r");
            if(fp == NULL){
                    printf("Cannot open file\n");
                    exit(0);
            }
            i=0;
            fgets(buf,256,fp);  
    // Validates that person has a last name and grade
    	while(!feof(fp)){
            if(buf[0] != '|' && buf[strlen(buf)-2] != '|')
            	{	
    // Splits the last name, first name, and grade
            ch = strchr(buf,'\n'); 
                    if(ch != NULL) *ch = '\0';
                    else break;
                    ch = strchr(buf,'|'); 
                    ch2 = strrchr(buf,'|'); 
                    if(ch != NULL)
                    {
                    *ch = '\0';ch1 = ++ch2; 
                    }
                    else break;
                    ch++; 
                    strcpy(ch3,ch); 
                    ch2=strchr(ch3,'|'); 
                    *ch2='\0'; 
                    gradeCalculate = atoi(ch1);	
                    strcpy(student[i].lastName,buf);
                    strcpy(student[i].firstName,ch3); 
                    student[i].points = atof(ch1);  
    // Calculates the letter grade
            switch(gradeCalculate / 10)
    		{
    			case 10:
    				student[i].grade = 'A';
    				break;
    			case 9:
    				student[i].grade = 'A';
    				break;
    			case 8:
    				student[i].grade = 'B';
    				break;
    			case 7:
    				student[i].grade = 'C';
    				break;
    			default:
    				student[i].grade = 'F';
    			}
    // Increments letter counter
    			if(gradeCalculate >= 90) a++;
    			if(gradeCalculate >= 80 && gradeCalculate < 90) b++;    
    			if(gradeCalculate >= 70 && gradeCalculate < 80) c++;
    			if(gradeCalculate < 70) f++;                
         		fgets(buf,256,fp);
         		i++; // Increments the student array
         		}
    		else
            {
            	fp2 =  fopen("REJECTS.txt","a");
            	fprintf(fp2,"%s",buf);
            	fclose(fp2);
            	fgets(buf,256,fp);
    		}//
    } // End of While statement
    // Prints the format for the Grade list
    
            n = i;
    		printf("\n 			        Grade list for CS-XXXX \n");
    		printf("        			 ---------------------- \n\n");
    		printf("Last Name				First Name");	
    		printf("				Points	Grade \n");
    		printf("---------				----------");
    		printf("				------	----- \n");
    // Runs a loop to print the array information
            for (i = 0; i < n; i++){	
    // Prints the array of students
            	printf("%-30s		%-30s		%4.2f	",student[i].
            		lastName,student[i].firstName,student[i].points);
    			printf("%c\n",student[i].grade);
    		}
    // Prints the class summary			
    		printf("\n         Grade Summary for CS-XXXX \n");
    		printf("         ------------------------- \n\n");
    		printf("		# of A's	%d\n",a);
    		printf("		# of B's	%d\n",b);
    		printf("		# of C's	%d\n",c);
    		printf("		# of D's	%d\n",d);				
    		printf("		# of F's	%d\n",f);
            return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. OOP Question DB Access Wrapper Classes
    By digioz in forum C# Programming
    Replies: 2
    Last Post: 09-07-2008, 04:30 PM
  2. String splitting algorithm help
    By (TNT) in forum C++ Programming
    Replies: 7
    Last Post: 05-12-2007, 11:28 AM
  3. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 02:23 PM
  4. creating class, and linking files
    By JCK in forum C++ Programming
    Replies: 12
    Last Post: 12-08-2002, 01:45 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21