Thread: Need Help With String

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    34

    Need Help With String

    I got a small project to do. I have a file with some sentences on different lines of the text document. What I would like to do is get each word on the line separately. Lets say this is the text in the document:

    Hi Good Day
    My Name is Jake

    What I would like is to take specifically the word pointer "Hi", make some changes, then take "Good" , make some changes take "Day" make changes then stop (/0). Go to next line and continue the Process.

    Any Help?

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    What have you tried so far? Post your best attempt, and explain in as much detail as possible exactly what problems you are having. It would also help if you explained what these "changes" are supposed to be, and what you are supposed to do with the changed sentences (output to screen, same file, different file, etc).

  3. #3
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    I have tried thiss:

    Code:
    fgets(str,16,in2);
        printf ("%s",str);
        int i=0;
        while(str[i]!='\0')
        {
            while(str[i]!=' ')
            {
                printf (" This does not have /0 in it = %c \n",str[i]);
                i++;
            }
        }

    but it only gets the characters. I want the word that the characters make up. When i can get the full string, I want to put it into another function to find it in the text file, when it finds it,
    Currently, I am making a function so when it finds the word, the word (str) would point to the word next to it but using two separate pointers. Next(n) and Previous (p).
    So
    "Hi" would point to "Good" which will then point to "Day".

    Thus Far, I have,
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<string.h>
    #include<ctype.h>
    
    
    typedef struct node{
        char data[100];
        node *p,*n,*left,*right;
    }Node, *NodePtr;
    
    
    NodePtr MakeNode(char str[])
    {
        
        
        NodePtr p=(NodePtr) malloc (sizeof(Node));
        strcpy(p->data,str);
        p->left=NULL;
        p->n=NULL;
        p->p=NULL;
        p->right=NULL;
        return p;
    }
    
    
    NodePtr find(NodePtr root, char str[])
    {
        NodePtr curr=root ,tnp= MakeNode(str);
        
        if (root== NULL) return tnp;
        int cmp=strcmp(str,curr->data);
        while (cmp!=0)
        {
            if (cmp<0)
            {
                if (curr->left==NULL)
                {
                    curr->left=tnp;
                    return tnp;
                }
            curr=curr->left;
            }
            else
            {
                if (curr->right==NULL)
                {
                    curr->right=tnp;
                    return tnp;
                }
                curr=curr->right;
            }
        }
    return curr;
    }
    
    
    
    
    
    
    NodePtr adjust(FILE *in, NodePtr root)
    {
        NodePtr curr;
        char str[100];
        NodePtr tnp;
        while (!feof(in))
        {
            fscanf(in,"%s",str);
            tnp=find(root,str);
            
                if (tnp!=NULL)
                {
                    if (root->n==NULL)
                    tnp->n=adjust(in,curr->p);
                    
                }
        }
        return 0;
    }
    
    
    
    
    
    
    char main ()
    {
        NodePtr root=NULL, tnp;
        char str[16];
        
        FILE * in=fopen("C:\\Test\\input.txt","r");
        FILE* out=fopen("C:\\Test\\input.txt","a");
        FILE *in2=fopen("C:\\Test\\input.txt","r");
    
    
    /*    printf( " Enter The Words You Would Like To Add\n");
        scanf ("%s",&str);
        
     while (strcmp(str,"0")!=0)
        {
            
            fprintf(out," %s",str);
            scanf("%s",&str);
        }
        */
        
        while (!feof(in))
        {
            fscanf(in,"%s",str);
            NodePtr tnp=find(root,str);
            if (root==NULL) root=tnp;
            
        }
    adjust(in2,root);
    /*    printf( " Enter the Word you would like to find \n");
        scanf("%s",&str);
        
    printf (" We found it here %p ",find(root,str));
    
    
    printf ("\n In Order = "); 
    InOrder(root);
    printf ("\nPost Order = ");
    PostOrder(root);
    printf ("\nPre Order = ");
    PreOrder(root);
    
    
        fgets(str,16,in2);
        printf ("%s",str);
        int i=0;
        while(str[i]!='\0')
        {
            while(str[i]!=' ')
            {
                printf (" This does not have /0 in it = %c \n",str[i]);
                i++;
            }
        }*/
    fclose(out);
    fclose(in);
    getch();
    }

  4. #4
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    At the end of it all, All i want to accomplish is when a word is searched, it finds it and prints the other words on the same line but the words must be in a Binary Tree

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    A few basic things from your first bit of code:

    • What do you intend for that code to do. Currently it just prints a line, it never modifies the text/word. something like str[i] = 'x', to set the whole word to x's.
    • 16 bytes is awfully small for a line of text. Your data member of the struct is 100 bytes, so how can you ever come close to filling that up if you only read 16 bytes for a line? Try a line length of at least 100.
    • You should use sizeof in your fgets call: fgets(str, sizeof(str), in2) if you call fgets from the same function where you declare str. Otherwise, #define a macro, like MAX_LINE and use that instead of "magic numbers".
    • Your loops are broken. Imagine str contains a long word with no space characters. The first loop starts, str[0] is not '\0', so it enters the loop. Then, str[i] is not a space, so it enters the second loop, where it prints a letter and increments i. Pretty soon, you are dealing with memory that is not part of str. You need to make sure i is within bounds for str, i.e. it's < sizeof(str).
    • Perhaps you meant to stop when you find a space, or a null character, in which case you need one loop with a compound condition: while (i < sizeof(str) && i != '\0' && i != ' ')


    As for your second bit of code:

    • I don't understand why your struct contains pointers for p, n, left and right. Are you trying to implement a combination of linked lists and binary trees?
    • I would not suggest typedef'ing pointers, i.e. don't have a NodePtr type, just use Node *. It's too easy to lose track of how many times you need to dereference something to get to the object it points to when you typedef a pointer.
    • Read this FAQ: FAQ > Why it's bad to use feof() to control a loop - Cprogramming.com.
    • You never check to see if your files were opened successfully.
    • EDIT: Don't cast malloc. Read this link. Also, a much cleaner form that wont cause problems if you change the type of p is: Node *p = malloc(sizeof(*p));. Note the *p in the sizeof. That means "the size of the thing pointed to by p", which is exactly how much space you want to allocate.
    • Functions should do one thing and do it well, and it's name should reflect that. Your find function looks an awful lot like an insert function to me.
    • Once you update curr in the loop in your find() function, you need to call strcmp again with the new curr->data. Put a cmp = strcmp(str,curr->data) as the last line in your while loop.
    • You have a memory leak in that funciton, you always allocate a new node, tnp, but don't always free it, even if cmp is 0 and the word already exists.
    • Last thing to note, make sure your code is easy to read. Keeping good, clean indentation and code formatting makes it much less likely to make errors, and much easier to find and fix them if you do. Some good info here: SourceForge.net: Indentation - cpwiki. It also make it easier for us to help you.


    Frankly, I still find your description of the problem confusing. If you understand the problem but just can't convey it to me, perhaps you could post a link to the actual assignment. If you don't fully understand what it is you are trying to do, then you should not even touch the keyboard. Writing code is one of the last steps to solving a problem. A general approach I use:

    1. Understand the problem. Read the description, email your professor or TA if you have questions, etc.
    2. Plan your solution with a paper and pencil. Draw, write, etc, those steps you would take in more detail.
    3. Test your paper-and-pencil solution, and make sure it works like you expect.
    4. Turn that paper and pencil solution into pseudo code.
    5. Begin turning that pseudo code into real code. Sometimes it helps to start by typing your pseudo code as comments, and filling in real code around it.
    6. Work in "logical" chunks. For example, work on reading in the file first. Once you know you can do that successfully, then move on to the next part of the program.
    7. Only write 5-10 lines of code at a time. Stop, compile, and fix any errors or warnings that come up.
    8. Check for errors every place possible and print useful debugging messages if something fails. You can remove them later if you need to. The perror function, or strerror+errno are useful for this.
    9. I also think it's a good idea to write code that allocates and deallocates resources at the same time, so you don't forget to free them up later. A good 5-10 line chunk of code to write would be fopen(), check for NULL/errors and the fclose() call. Also, malloc(), check for NULL/errors and free().


    EDIT: Just saw your previous post. I was in the middle of writing this when you posted that, so I missed it. See my response below.
    Last edited by anduril462; 09-28-2012 at 06:08 PM. Reason: added casting malloc issue

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Ramkiller1 View Post
    At the end of it all, All i want to accomplish is when a word is searched, it finds it and prints the other words on the same line but the words must be in a Binary Tree
    That makes a lot more sense, but still a few things to clear up.

    Can you just print the whole line, or should it only be a list of the words on that line. For example, if the line was "one two three two one", and you search for the word "one", should it print "one two three two one" or just "one two three"?

    What if two lines contain the same word? Do you print all words from every line that contains the word, or just the first one, etc.

    These may help you figure out how best to organize your data structure.

  7. #7
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    It should just print one two three. The Find function would replace the "one" with the other one. I would think it prints both lines.

  8. #8
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    I was also thinking to put the first word on each line in the Binary Tree the other words that comes after the first word can go in a Link List.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Hmm...did you delete or edit a previous post that had the problem description? It sounded like this was a sort of thesaurus program, so lines might be:
    Code:
    happy glad elated ecstatic
    angry furious mad
    ...
    EDIT: I see you re-posted that.

    You can use fgets to read the whole line, and use strtok to split it up into individual words. Make sure you can do this no problem before moving on.
    Quote Originally Posted by Ramkiller1 View Post
    I was also thinking to put the first word on each line in the Binary Tree the other words that comes after the first word can go in a Link List.
    Sound like a pretty reasonable way to handle it. I would use the following two data structures:
    Code:
    #define MAX_WORD_LEN    100
    
    // do the typedef first so you can use the new type name in the struct definition iteself
    typedef struct wordList    wordList;  // you can typedef it to the same name without the 'struct' part
    struct wordList {
        char word[MAX_WORD_LEN+1];  // +1 for the null byte
        wordList *next;
        // I see no need for a prev pointer since you don't need to go forward and backward through the list
    };
    
    typedef struct wordTree    wordTree;
    struct wordTree {
        wordList *words;
        wordTree *left;
        wordTree *right;
    };
    Then I would work on just your linked list functions. Make sure you can add to the list, print the list and free up all the resources when you're done. Test it by reading a line, adding all the words and printing them out, then freeing everything. Do that for each line in the file.

    After that work on your binary tree. Make sure you can add a node, find, print and free up resources. Just add a single word, don't worry about the linked list part yet. You can even teporarily change the wordTree struct to use a char array instead of a wordList *, and just store the word there. Once you know your binary tree is 100% working, you can combine the tree and the list code to have your final solution.

  10. #10
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    Thanks will try now

  11. #11
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    Having a very hard time using strtok.
    The pa
    This is my code.

    Code:
    char main ()
    {
    	NodePtr root=NULL, tnp;
    	char str[16];
    	char *result=NULL;
    	char delim[10]=' '; //Getting an error on this line for ' '
    	
    	FILE * in=fopen("C:\\Test\\input.txt","r");
    
    
    	
    	while (!feof(in))
    	{
    		fscanf(in,"%s",str);
    		NodePtr tnp=find(root,str);
    		if (root==NULL) root=tnp;
    		
    	}
    
    
    	fgets(str,16,in2);
    	printf ("%s",str);
    	int i=0;
    	result=strtok(str,delim);
    	printf ("%s",result);
    
    
    fclose(out);
    fclose(in);
    getch();
    }

  12. #12
    Registered User
    Join Date
    Sep 2012
    Posts
    34
    Got it

  13. #13
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You're still using feof to control your loop, which is bad. Read the link I provided in post #5 (the red text are links).

    Also, you need to start checking the return value of your functions like fscanf and fgets. Make sure they were successful before your program continues on. If your data is bogus, then no point in processing it, you'll just get garbage output.

    You can actually use fscanf and fgets to control the loops, which takes care of the feof problem and checking their return values:
    Code:
    while (fscanf(in, "%s", str) == 1)
    ...
    while (fgets() != NULL)
    Get in the habit of reading documentation for the functions you use. fscanf, for example, returns the number of things successfully scanned, i.e. how many of the %s, %d, %c, etc format specifiers it could match. Since you're asking for one word each time you call it ("%s"), you should expect a return value of 1, as in the first example I gave here.

    Oh, and don't know how I missed this before, but main returns an int, not a char. I recommend always starting with the following:
    Code:
    int main(void)
    {
        return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 22
    Last Post: 07-28-2011, 01:26 PM
  2. Replies: 7
    Last Post: 06-16-2011, 06:21 PM
  3. Replies: 12
    Last Post: 03-07-2011, 01:24 AM
  4. Replies: 5
    Last Post: 05-09-2010, 10:58 AM
  5. Replies: 1
    Last Post: 10-31-2005, 11:36 AM