Hi, I need some help here, i've been writing some
code for an assignment and it is mostly about
pointers and string manipulations. It runs but
crashes and I think it might be from over-
valuating some strings maybe not. I have
written in check points to make sure each
function passes through but quits at
findFirstPath loop, I had kept running the
program through as i added more and more
code. It had stopped when I near finished I
believed it to just be because I hadn't finished
the functions I called.Any clarification would be great.
Thanks
#include <stdio.h> #include <stdlib.h> #include <ctype.h> /* The following matrix defines how compounds (labelled A to T) can be synthesised to other compounds. The first letter in each row is a starting compound, and each subsequent letter gives the list of compound to which this starting compound can be synthesised. So the string "OIJN" indicates that compound O can be converted to componds I, J, or N. Note that compounds that cannot be synthesised to any other compound do not have a corresponding string in the matrix. */ #define MAXSTRING 10 // maximum length of the synthesis string. char synthesisMatrix[][MAXSTRING] = { "BAH", "DCI", "EJ", "FK", "GFLM", "HBDG", "ICJ", "JEO", "KFL", "LF", "MQ", "NJ", "OIJN", "QMP", "RQS", "SMT", "" }; // Note that last entry is the empty string, which means that the last row can be // detected when the first character in the row is the '\0' (nul) character. This // means that is is not necessary to know the number of rows in the matrix. // Some definitions #define TRUE 1 #define FALSE 0 #define MAXNUMCOMPOUNDS 26 // No more than 26 compounds defined #define MINCOMPOUND 'A' // Smallest letter for compound #define MAXCOMPOUND 'T' // Maximum letter for compound // Prototypes int userInterface(char *, char *); void findFirstPath(char *, char , char ); char findNextCompound(char *, char *); char *findSynthesisString(char ); void printSynthesisPath(char *); /*----------------------------------------------------------------- -------- Function: main Description: Overall control of the program. Calls userInterface to get input from the user. When userInterface returns FALSE, it signals the end of the program. If it returns TRUE, then it has provided values for initialCompound and finalCompound and calls findFirstPath to try to find a path. If a path is found call printSynthesisPath to print the results, otherwise print message that path could not be found. ------------------------------------------------------------------- --------*/ int main() { char pathString[MAXNUMCOMPOUNDS+1]; // char array for storing path char initialCompound; // character for initial compound char finalCompound; // character for final compound int flag; // flag for controlling the loop do { flag = userInterface(&initialCompound, &finalCompound); if(flag==TRUE) { findFirstPath(pathString, initialCompound, finalCompound); if(*pathString != '\0') printSynthesisPath(pathString); else printf("Synthesis path could not be found\n"); } } while(flag!=FALSE); printf("Terminating...\n"); system("pause"); } /*----------------------------------------------------------------- -------- Function: userInterface Description: Gets input from the user. This function should return either TRUE or FALSE. If it returns TRUE, then two different characters should have been obtained from the user and saved using the pointers. ------------------------------------------------------------------- -------*/ int userInterface(char *initialPtr, char *finalPtr) { int choice;//This will decide return value printf("What would you like to do?\n1)Enter in First and Last Compound?\n2)Exit?\n"); do{ scanf("%d", &choice); if(choice==2){ return FALSE; } else if(choice<1 || choice>2){ printf("please choose 1 or 2\n"); } if(choice==1){ fflush(stdin); printf("OK! Now enter first compound : (A-T)\n"); while(*initialPtr<MINCOMPOUND || *initialPtr>MAXCOMPOUND){ fflush(stdin); scanf("%c", initialPtr); if(*initialPtr<MINCOMPOUND || *initialPtr>MAXCOMPOUND){ printf("WRONG Enter in between A-T\n"); } } printf("Now the Second compound : (A- T)\n"); while(*finalPtr<MINCOMPOUND || *finalPtr>MAXCOMPOUND){ fflush(stdin); scanf("%c", finalPtr); if(*finalPtr<'A' || *finalPtr>'Z'){ printf("WRONG Enter in between A-T\n"); } } printf("\n%c %c\n", *initialPtr, *finalPtr); return TRUE; } }while(choice!=1&&choice!=2); } /*----------------------------------------------------------------- -------- Function: findFirstPath Description: The principal function to find a synthesis path. ------------------------------------------------------------------- -------*/ void findFirstPath(char *pathPtr, char initialCompound, char finalCompound) { char *alreadySeenPtr, alreadySeenArray[MAXSTRING], *currentPtr, *synthesisPtr, nextCompound;//Assigning Arrays/Pointers int flag;//flag for control of loop alreadySeenPtr=alreadySeenArray; *alreadySeenPtr='\0'; currentPtr=pathPtr; *currentPtr=initialCompound; *(currentPtr+1)='\0'; flag=TRUE; while(flag==TRUE){ if(strchr(alreadySeenPtr, *currentPtr)==NULL){ *alreadySeenPtr=*currentPtr; alreadySeenPtr++; *alreadySeenPtr='\0'; } synthesisPtr=findSynthesisString(*currentPtr); if(strchr(synthesisPtr, finalCompound)!=NULL){ currentPtr++; *currentPtr=finalCompound; *(currentPtr+1)='\0'; flag=FALSE; } else{ nextCompound=findNextCompound(synthesis Ptr, alreadySeenPtr); if(nextCompound!='\0'){ currentPtr++; *currentPtr=nextCompound; *(currentPtr+1)='\0'; } else{ if(*currentPtr==initialCompound){ *currentPtr='\0'; flag=FALSE; } else{ *currentPtr='\0'; currentPtr--; } } } } printf("\nCheck firstPath\n"); } /*----------------------------------------------------------------- -------- Function: findNextCompound Description: Finds next compound in a synthesis path that has not yet been seen. Returns the nul character if all compounds in the synthesis path are in the already seen array. ------------------------------------------------------------------- -------*/ char findNextCompound(char *synthesisPtr, char *alreadySeenPtr) { char *searchPath, *alreadySearched, character; int flag; searchPath=synthesisPtr; alreadySearched=alreadySeenPtr; flag=TRUE; while(flag==TRUE){ if(strchr(searchPath, *alreadySearched)==NULL){ *(alreadySearched+1)=*searchPath; *searchPath='\0'; } if(strchr(searchPath, *alreadySearched)!=NULL){ character='\0'; return character; flag=FALSE; } } } /*----------------------------------------------------------------- -------- Function: findSynthesisString Description: Finds the synthesis string in the synthesisMatrix (i.e. row) for a given compound. ------------------------------------------------------------------- -------*/ char *findSynthesisString(char compound) { char first, *firstPtr, *rowaddress; int flag; first=compound; firstPtr=&synthesisMatrix[MAXNUMCOMPOU NDS][FALSE]; rowaddress=strchr(firstPtr, first); if(*rowaddress==first){ return rowaddress; } if(*rowaddress!=first){ rowaddress=strchr(firstPtr, '\0'); return rowaddress; } printf("\nCheck SynthesisString\n"); } /*----------------------------------------------------------------- -------- Function: printSynthesisPath Description: Prints a synthesis path in the form of A->B->H (when path is defined as "ABH". Guard against receiving an empty string. ------------------------------------------------------------------- -------*/ void printSynthesisPath(char *pathPtr) { char *printPath; int i; printPath=pathPtr; printf("The Path is :\n"); for(i=0;i<=MAXSTRING-1; i++){ printf("%c- >",*(printPath+i)); } printf("\nCheck Print"); }
In my testing it seems to be crashing inside the function: char *findSynthesisString(char compound)This is the beginning of your problems:
firstPtr=&synthesisMatrix[MAXNUMCOMPOUNDS][FALSE];Consider that you are defining "MAXNUMCOMPOUNDS" as 26 while only giving "synthesisMatrix" 17 char pointers. It gets worse still when you do this:
rowaddress=strchr(firstPtr, first);You should always check if "strchr" fails and gives you a NULL pointer; you can't assume the function will succeed.
I'm not sure exactly what is the desired result of the function so it's hard for me to say what needs to be done to fix it.
Is this meant to be plain C or C++?
I've done a little bit of changing, and I've managed it to
improve. What I'm trying to do is that from the global array
enter in 2 compounds and find a path,(such as one path is
"BAH", enter 1st compound B, 2nd H you should result with
B->A->H)Now i worked out the path and if I enter in B and H my
program says the path is possible but just puts B->H.#include <stdio.h> #include <stdlib.h> #include <ctype.h> /* The following matrix defines how compounds (labelled A to T) can be synthesised to other compounds. The first letter in each row is a starting compound, and each subsequent letter gives the list of compound to which this starting compound can be synthesised. So the string "OIJN" indicates that compound O can be converted to componds I, J, or N. Note that compounds that cannot be synthesised to any other compound do not have a corresponding string in the matrix. */ #define MAXSTRING 10 // maximum length of the synthesis string. char synthesisMatrix[][MAXSTRING] = { "BAH", "DCI", "EJ", "FK", "GFLM", "HBDG", "ICJ", "JEO", "KFL", "LF", "MQ", "NJ", "OIJN", "QMP", "RQS", "SMT", "" }; // Note that last entry is the empty string, which means that the last row can be // detected when the first character in the row is the '\0' (nul) character. This // means that is is not necessary to know the number of rows in the matrix. // Some definitions #define TRUE 1 #define FALSE 0 #define MAXNUMCOMPOUNDS 26 // No more than 26 compounds defined #define MINCOMPOUND 'A' // Smallest letter for compound #define MAXCOMPOUND 'T' // Maximum letter for compound // Prototypes int userInterface(char *, char *); void findFirstPath(char *, char , char ); char findNextCompound(char *, char *); char *findSynthesisString(char ); void printSynthesisPath(char *); /*------------------------------------------------------------------------- Function: main Description: Overall control of the program. Calls userInterface to get input from the user. When userInterface returns FALSE, it signals the end of the program. If it returns TRUE, then it has provided values for initialCompound and finalCompound and calls findFirstPath to try to find a path. If a path is found call printSynthesisPath to print the results, otherwise print message that path could not be found. ---------------------------------------------------------------------------*/ int main() { char pathString[MAXNUMCOMPOUNDS+1]; // char array for storing path char initialCompound; // character for initial compound char finalCompound; // character for final compound int flag; // flag for controlling the loop do { flag = userInterface(&initialCompound, &finalCompound); if(flag==TRUE) { findFirstPath(pathString, initialCompound, finalCompound); if(*pathString != '\0') printSynthesisPath(pathString); else printf("Synthesis path could not be found\n"); } } while(flag!=FALSE); printf("Terminating...\n"); system("pause"); } /*------------------------------------------------------------------------- Function: userInterface Description: Gets input from the user. This function should return either TRUE or FALSE. If it returns TRUE, then two different characters should have been obtained from the user and saved using the pointers. --------------------------------------------------------------------------*/ int userInterface(char *initialPtr, char *finalPtr) { int choice;//This will decide return value printf("What would you like to do?\n1)Enter in First and Last Compound?\n2)Exit?\n"); do{ scanf("%d", &choice); if(choice==2){ return FALSE; } else if(choice<1 || choice>2){ printf("please choose 1 or 2\n"); } if(choice==1){ fflush(stdin); printf("OK! Now enter first compound : (A-T)\n"); while(*initialPtr<MINCOMPOUND || *initialPtr>MAXCOMPOUND){ fflush(stdin); scanf("%c", initialPtr); if(*initialPtr<MINCOMPOUND || *initialPtr>MAXCOMPOUND){ printf("WRONG Enter in between A-T\n"); } } printf("Now the Second compound : (A-T)\n"); while(*finalPtr<MINCOMPOUND || *finalPtr>MAXCOMPOUND){ fflush(stdin); scanf("%c", finalPtr); if(*finalPtr<'A' || *finalPtr>'Z'){ printf("WRONG Enter in between A-T\n"); } } printf("\n%c %c\n", *initialPtr, *finalPtr); return TRUE; } }while(choice!=1&&choice!=2); } /*------------------------------------------------------------------------- Function: findFirstPath Description: The principal function to find a synthesis path. --------------------------------------------------------------------------*/ void findFirstPath(char *pathPtr, char initialCompound, char finalCompound) { char *alreadySeenPtr, alreadySeenArray[MAXSTRING], *currentPtr, *synthesisPtr, nextCompound;//Assigning Arrays/Pointers int flag;//flag for control of loop alreadySeenPtr=alreadySeenArray; *alreadySeenPtr='\0'; currentPtr=pathPtr; *currentPtr=initialCompound; *(currentPtr+1)='\0'; flag=TRUE; while(flag==TRUE){ if(strchr(alreadySeenPtr, *currentPtr)==NULL){ *alreadySeenPtr=*currentPtr; alreadySeenPtr++; *alreadySeenPtr='\0'; } synthesisPtr=findSynthesisString(*currentPtr); if(strchr(synthesisPtr, finalCompound)!=NULL){ currentPtr++; *currentPtr=finalCompound; *(currentPtr+1)='\0'; flag=FALSE; } else{ nextCompound=findNextCompound(synthesisPtr, alreadySeenPtr); if(nextCompound!='\0'){ currentPtr++; *currentPtr=nextCompound; *(currentPtr+1)='\0'; } else{ if(*currentPtr==initialCompound){ *currentPtr='\0'; flag=FALSE; } else{ *currentPtr='\0'; currentPtr--; } } } } printf("\nCheck firstPath\n"); } /*------------------------------------------------------------------------- Function: findNextCompound Description: Finds next compound in a synthesis path that has not yet been seen. Returns the nul character if all compounds in the synthesis path are in the already seen array. --------------------------------------------------------------------------*/ char findNextCompound(char *synthesisPtr, char *alreadySeenPtr) { char *searchPath, *alreadySearched, character; int flag; searchPath=synthesisPtr; alreadySearched=alreadySeenPtr; flag=TRUE; while(flag==TRUE){ if(strchr(searchPath, *alreadySeenPtr)!=NULL){ flag=FALSE; } if(strchr(synthesisPtr, *alreadySeenPtr)==NULL){ *(alreadySearched+1)=*searchPath; *searchPath='\0'; } } } /*------------------------------------------------------------------------- Function: findSynthesisString Description: Finds the synthesis string in the synthesisMatrix (i.e. row) for a given compound. --------------------------------------------------------------------------*/ char *findSynthesisString(char compound) { char first, *firstPtr, *rowaddress; int flag,i; first=compound; for(i=0; i<MAXNUMCOMPOUNDS; i++){ rowaddress=memchr(synthesisMatrix[i], first, 1); if(rowaddress!=NULL){ printf("\nCheck SynthesisString\naddress: %d character: %c\n", rowaddress, first); return rowaddress; break; } } } /*------------------------------------------------------------------------- Function: printSynthesisPath Description: Prints a synthesis path in the form of A->B->H (when path is defined as "ABH". Guard against receiving an empty string. --------------------------------------------------------------------------*/ void printSynthesisPath(char *pathPtr) { char *printPath; int i, length; printPath=pathPtr; length=strlen(pathPtr); printf("The Path is :\n"); for(i=0;i<=length; i++){ printf("%c",printPath[i]); if(i<length-1){ printf("->"); } } printf("\nCheck Print\n"); }
And mean't for just C.
Now I think I understand the objective - Get the first and last character from the user and show the path it takes in the character array. If this is what you are trying to do you are severely over complicating things. It could be much simpler, your passing around lots of pointers, when ints would do fine to reference the global array.
Take this for example:
int findSynthesisString(char compound) { int counter = 0; //This can work because you already define //the last element of the array as "" while(synthesisMatrix[counter][0] != '\0') { if (synthesisMatrix[counter][0] == compound) { return counter; } counter++; } printf("\nCheck SynthesisString\n"); return -1; }Then all you would have to do is check if it's -1, if it is it wasn't found otherwise you have the pointer number (i.e synthesisMatrix[counter]).
Edit:
In fact you could modify the same function to check if the last character matches as well using "strlen(synthesisMatrix[counter])".
lol, I know I have made it quite a bit complicated the focus is
really on strings and pointers. that function itself returns an
address to findFirstPath that will then call the function
findNextCompound passing that strings address it will add the
compounds approaching to the final compound to the process
and print the end result. I understand where your coming from lol
I guess my only problem now is that i confused myself on how I
missed adding the compounds approaching the final because it
will only print the first and final compound if the path does exist.
[edit]
Forgot to mention what the problem was - You assigned *currentPtr to initialCompound, incremented and then assigned finalCompound to it(doing nothing about the creamy innards ;).
[/edit]
I can't say I like using pointers this way(or if it is technically correct), but have a quick look at this(modified findFirstPath):if(strchr(synthesisPtr, finalCompound)!=NULL){ currentPtr++; synthesisPtr++; while(strchr(synthesisPtr, finalCompound)!=NULL) { *currentPtr = *synthesisPtr; synthesisPtr++; currentPtr++; } *(currentPtr)='\0'; flag=FALSE; } else {
One thing I was going to mention - I would really suggest using consistent formatting of whitespace, I find it makes things a little easier, especially to debug ;)
Hehe yeah i know that the white space has been through the
wash, I keep throw stuffing around trying new things. That
modified version had seem to solve the problem to print the
approaching compounds if the path existed, now if there is no
path it just stalls right when it reaches the findSynthesisString
function.Instead of just jumping forward to say no path.
I don't really want to do much more because this is your homework
and all.....Anyway just a couple of minor changes, in printSynthesisPath
you can check for failure because length will be one.There is also a bug in your selection menu, if you type in a letter
it goes into an infinite loop.char *findSynthesisString(char compound) { char first, *firstPtr, *rowaddress; int flag,i; rowaddress = NULL; first=compound; for(i=0; i<MAXNUMCOMPOUNDS; i++){ rowaddress=(char *)memchr(synthesisMatrix[i], first, 1); if(rowaddress!=NULL){ printf("\nCheck SynthesisString\naddress: %d character: %c\n", rowaddress, first); break; } } return rowaddress; }
And:void findFirstPath(char *pathPtr, char initialCompound, char finalCompound) { char *alreadySeenPtr, alreadySeenArray[MAXSTRING], *currentPtr; char *synthesisPtr, nextCompound;//Assigning Arrays/Pointers int flag;//flag for control of loop alreadySeenPtr=alreadySeenArray; *alreadySeenPtr='\0'; currentPtr=pathPtr; *currentPtr=initialCompound; *(currentPtr+1)='\0'; flag=TRUE; while(flag==TRUE){ if(strchr(alreadySeenPtr, *currentPtr)==NULL){ *alreadySeenPtr=*currentPtr; alreadySeenPtr++; alreadySeenPtr='\0'; } synthesisPtr=findSynthesisString(*currentPtr); if (synthesisPtr == NULL) break; if(strchr(synthesisPtr, finalCompound)!=NULL){ currentPtr++; synthesisPtr++; while( strchr(synthesisPtr, finalCompound)!=NULL) { *currentPtr = *synthesisPtr; synthesisPtr++; currentPtr++; } *(currentPtr)='\0'; flag=FALSE; } else { nextCompound=findNextCompound(synthesisPtr, alreadySeenPtr); if(nextCompound!='\0'){ currentPtr++; *currentPtr=nextCompound; *(currentPtr+1)='\0'; } else { if(*currentPtr==initialCompound){ *currentPtr='\0'; flag=FALSE; } else { *currentPtr='\0'; currentPtr--; } } } } printf("\nCheck firstPath\n"); }
I found another one :( void findFirstPath(char *pathPtr, char initialCompound, char finalCompound) { char *alreadySeenPtr, alreadySeenArray[MAXSTRING], *currentPtr; char *synthesisPtr, nextCompound;//Assigning Arrays/Pointers int flag;//flag for control of loop alreadySeenPtr=alreadySeenArray; *alreadySeenPtr='\0'; currentPtr=pathPtr; *currentPtr=initialCompound; *(currentPtr+1)='\0'; flag=TRUE; while(flag==TRUE){ if(strchr(alreadySeenPtr, *currentPtr)==NULL){ *alreadySeenPtr=*currentPtr; alreadySeenPtr++; alreadySeenPtr='\0'; } synthesisPtr=findSynthesisString(*currentPtr); if (synthesisPtr == NULL) break; if (strchr(synthesisPtr, finalCompound)!=NULL){ currentPtr++; synthesisPtr++; while( strchr(synthesisPtr, finalCompound)!=NULL) { *currentPtr = *synthesisPtr; synthesisPtr++; currentPtr++; } *(currentPtr)='\0'; flag=FALSE; } else { if (alreadySeenPtr == NULL) break; nextCompound=findNextCompound(synthesisPtr, alreadySeenPtr); if(nextCompound!='\0'){ currentPtr++; *currentPtr=nextCompound; *(currentPtr+1)='\0'; } else { if(*currentPtr==initialCompound){ *currentPtr='\0'; flag=FALSE; } else { *currentPtr='\0'; currentPtr--; } } } } printf("\nCheck firstPath\n"); }
Yes (14) | ![]() | |
No (14) | ![]() | |
I don't know (15) | ![]() |