0

I will say honestly, this isn't my code. It's my brother's who's studying with me but he's a ahead of me.
Please notice char *str and char *resultString in the function char *replaceWord().

/*Suppose you have a template letter.txt. You have to fill in values to a template. Letter.txt looks something like this:
Thanks {{name}} for purchasing {{item}} from our outlet {{outlet}}. Please visit our outlet {{outlet}} for any kind of problems. We plan to serve you again soon.
You have to write a program that will automatically fill the template.For this, read this file and replace these values:
{{name}} - Harry 
{{item}} - Table Fan 
{{outlet}} - Ram Laxmi fan outlet
Use file functions in c to accomplish the same.*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * replaceWord(const char * str, const char * oldWord, const char * newWord)
{
    char * resultString;
    int i, count = 0;
    int newWordLength = strlen(newWord);
    int oldWordLength = strlen(oldWord);

    for (i = 0; str[i] != '\0'; i++)
    {
        if (strstr(&str[i], oldWord) == &str[i])
        {
            count++;
            //Jumping over the word and continuing
            i = i + oldWordLength - 1;
        }
    }
        //dynamically allocation memory to resultString since it can be big or samll depending on the size of the newWord.
        /*i = old string length , count = no. of times the word appeared in the string, 
        newWordLength-oldWordLength=difference between the new word and the old word
        +1 for the null character '\0'
        Basically we are saying that add the size required for the newWord to the strings length i.e i;
        */
    resultString = (char *)malloc(i + count * (newWordLength - oldWordLength) + 1);

    i = 0; //refreshing the i for the while loop
        while (*str)
        {
            if (strstr(str, oldWord) == str)
            {
                strcpy(&resultString[i], newWord);
                i += newWordLength;
                str += oldWordLength;
            }
            else
            {
                resultString[i] = *str;
                i+=1;
                str+=1;
            }
        }
        resultString[i] = '\0';
        return resultString;
}
int main()
{
    FILE *ptr = NULL;
    FILE *ptr2 = NULL;
    ptr = fopen("letter.txt", "r");     //where the template is stored
    ptr2 = fopen("newLetter.txt", "w"); //where the new bill will be stored.
    char str[200];
    fgets(str, 200, ptr); //store the bill template in the str variable.
    printf("The original bill template is : %s\n", str);

    //Calling the replacing fucntion
    char *newStr = str; //newStr will store the new bill i.e generated
    newStr = replaceWord(str, "{{name}}", "Mary");
    newStr = replaceWord(newStr, "{{item}}", "Waffle Machine");
    newStr = replaceWord(newStr, "{{outlet}}", "Belgium Waffle");
    printf("\nThe bill generated is:\n%s", newStr);
    fprintf(ptr2, "%s", newStr);
    fclose(ptr);
    fclose(ptr2);
    return 0;
}

Can someone explain why the pointer *str and *resultString are expressed different ways in the program and what are they doing? Sometimes it's *str, &str or str[i]. Please explain. I know that a pointer is used to keep the address of the other variables but this code is still a mystery to me. Also why was the function a pointer?

NOTE:"He said that's how it works" when I asked how. Please help!! I can't focus on other things. If you can't explain ;a link of explanation would be fine as well.

Shambhav
  • 813
  • 7
  • 20
el Drago
  • 35
  • 5
  • `&str[i]` is simply an awkward `str + i`. There isn't any difference in how they are handled. `str[i]` in index notation is equivalent to `*(str + i)` in pointer notation. So `&str[i]` is `&*(str + i)` which of course is just `str + i` (the `&*` effectively cancel each other) A few links that provide basic discussions of pointers may help. [Difference between char *pp and (char*) p?](https://stackoverflow.com/a/60519053/3422102) and [Pointer to pointer of structs indexing out of bounds(?)...](https://stackoverflow.com/a/60639540/3422102) (ignore the titles, the answers discuss pointer basics) – David C. Rankin May 28 '21 at 03:21
  • The key here is that both `[..]` and `*` (as in `pointer[..]` and `*pointer`) dereference `pointer`. The `[..]` form provides a simple way to provide an *offset* and *dererence* (e.g. `pointer[i]`) is the derererenced value of `pointer + i` (e.g. `*(pointer + i)`). – David C. Rankin May 28 '21 at 03:26
  • I highly recommend the [comp.lang.c FAQ](http://www.c-faq.com/), particularly section 6. – Keith Thompson May 28 '21 at 05:07

1 Answers1

0
Sometimes it's *str, &str or str[i]

Those are operators.

*str

str is a poitner to a char, and having a * over it dereferences it. Meaning it fetches the value from the memory that it is pointing to. A pointer may not always point to a variable though, it can be any arbitrary memory address. But dereferencing memory that is not yours will result in Segmentation fault which is the my most beloved error that occurs almost everytime when processing arrays.

str[i]

This is the same as *(str + i). Meaning it increments the memory address by i * sizeof(<datatype of what str points to>). Then it fetches the value from that incremented address. This is used for getting elements of an array.

&str

This just given the address of the variable str, which is a pointer. So, it returns a pointer to a pointer(ie. str). A pointer to a pointer can exist.

The function is not a pointer. Instead, it returns a pointer which is *resultString. It is so that a string can be returned. The string had been initialized in this line:

resultString = (char *)malloc(i + count * (newWordLength - oldWordLength) + 1);

The comment explaining this is not complete.

//dynamically allocation memory to resultString since it can be big or samll depending on the size of the newWord.
        /*i = old string length , count = no. of times the word appeared in the string, 
        newWordLength-oldWordLength=difference between the new word and the old word
        +1 for the null character '\0'
        Basically we are saying that add the size required for the newWord to the strings length i.e i;
        */

It also misses one key reason why malloc is being used instead of normal allocation. malloc allocates your variables on the heap which is shared among all functions and threads. While normal initialization would allocate it on the stack which is popped off when the function ends. So, no use after the function with the stack, so it should be used on the heap. And it is also for dynamic allocation.

Shambhav
  • 813
  • 7
  • 20
  • Thanks to every one who replied. David C. Rankin replies simplifies somethings to understand but after seeing @Shambhav Gautam 's answer, my doubts were cleared , Thanks to both of you. – el Drago May 28 '21 at 04:21