0

I'm trying to write a piece of code in C which takes an input(as string) from the file and adds it at the end of another string and prints it. The program compiles perfectly in Visual Studio 2013 but crashes during run. Can anyone please help me identify the problem with the code.

Here is the code:

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
int main()
{
    char input[255];
    char str1 = "caingb";
    char str2 = " ";
    FILE *f;
    f = fopen("rockyou.txt", "rt");
    while (fgets(input, sizeof(input), f))
    {
        str2 = str1 + input;
        printf("%s", str2);
    }
    fclose(f);
    return(0);
}

These are the three warning messages I'm getting:

  • Line 8: warning C4047: 'initializing' : 'char' differs in levels of indirection from 'char [7]
  • Line 9: warning C4047: 'initializing' : 'char' differs in levels of indirection from 'char [2]
  • Line 14: warning C4047: '=' : 'char' differs in levels of indirection from 'char *
M.M
  • 138,810
  • 21
  • 208
  • 365

2 Answers2

0

The easiest way to concatenate strings is with asprintf (for allocating sprintf, if you have it):

char *result;
char *a = "foo";
char *b = "barco";
asprintf(&result, "%s%s", a, b);

Note how easily this can deal with three or more strings, or interspersing stuff like in

asprintf(&result, "C:/%s/%s.exe", a, b);

Yours crashes because of the misdeclarations of str1 and str2 as char instead of pointers to char (that's what the warning messages tell you in some hard to understand way). Furthermore, C is not Java, and string concatenation is not done with +.

A good programmer would test result being non-NULL and probably free(result) once no longer needed.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • Thank you @Jens . I will try to incorporate the same logic through **asprintf** too and will also keep your tips in mind. I learnt a lot today. – Abhishek Pandey May 07 '17 at 20:14
  • Update: Coundn't find and use **asprintf()** in visual studio 2013. `#include #include #include #include int main() { char input[255]; char* str1 = "caingb"; char* str3; FILE *f; f = fopen("rockyou.txt", "rt"); while (fgets(input, sizeof(input), f)) { char* str2 = input; asprintf(&str3, "%s%s", str1, str2); } free(str3); fclose(f); return(0); }` This gives the warning as : **warning C4013: 'asprintf' undefined; assuming extern returning int** – Abhishek Pandey May 07 '17 at 20:31
  • @AbhishekPandey Hmm. I'm not terribly familiar with MS products. If it hasn't been asked, maybe it would make for a good question (after your research comes up empty) how to find or roll your own asprintf under Windows. – Jens May 07 '17 at 21:10
  • 1
    `asprintf` is not a Standard C function – M.M May 07 '17 at 22:40
-2

If you like to concatenate strings in C you have to use strcat . If you like to copy one string to another you have to use strcpy ... In a few words for string assignments in C you have to use a built in function (strcpy, strcat, memcpy, snprintf etc). You can't just simply use the = operator as you do!

So your code would be something like this:

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
int main()
{  
    char input[255];
    char *str1 = (char*)malloc(sizeof(char)*10);
    strcpy(str1,"caingb");
    char *str2=(char)0; //point to null..for initilization!
    FILE *f;
    f = fopen("rockyou.txt", "rt");
    while (fgets(input, sizeof(input), f))
    {
        str2=(char*)malloc(sizeof(char)*(strlen(str1)+strlen(input))+1);
        strcpy(str2,str1);
        strcat(str2,input);
        printf("%s", str2);
        free(str2);
    }
    fclose(f);
    free(str1);
    return(0);
}

At the 2 lines of the code above that malloc function appears, you are basically allocating space on the memory, to store the variables that malloc gets called from. In your for the second malloc you need the size of each character (sizeof(char)) multiplied times the amount of the length of string 1 (strlen(str1)) plus the length of string 2 ('strlen(input)). That will give you the required memory in HEAP of your program to storestr2. For the first malloc i am just multiplying it by 10, since"caingb"` i 6 chars (so i am reserving a few more bytes...not a good strategy if you want to be a good coder ;-) ). Later by calling free you are de-allocating the space you reserved with malloc, because if you don't it will stick like that into memory even after program is done executing!

A more abstract idea of malloc (for example purposes) would be

char* string=malloc(15);

...and like that you allocated 15 bytes of memory for the pointer char *string. So in whatever this pointer points to, must not exceeds 15 bytes, or you will have memory leaks (aka segmantation faults in C).

For further reading, search yourself about stack and heap of a program in C.

Also always try out the man pages through the terminal of yours ( in Linux) . An example of this would be:

man malloc ..and voilla you will get a manual page for what malloc does. It might seems a little bit harsh to read those man pages at first, but give time to yourself! There is also an online version of them at http://man.he.net/

P.S. I haven't run the above code, but thats the general idea.

Sarriman
  • 382
  • 5
  • 22
  • You haven't run the above code? Why? Then you'd find the bugs in it. – Jens May 07 '17 at 19:55
  • @jens Because i am on mobile, and its obvious what OP need to keep going...!! – Sarriman May 07 '17 at 19:58
  • 1
    Thanks you everyone for the help.@Diaman , thank you too. I ran your code and it worked without any issues. Can you help me understand what has been done at these two places: `char *str1 = (char*)malloc(sizeof(char)*10);` and `str2=(char*)malloc(sizeof(char)*(strlen(str1)+strlen(input))+1);` – Abhishek Pandey May 07 '17 at 20:02
  • Ok, but why do you type so much? Best practice in C is to **not cast malloc** and not multiply by `sizeof(char)` which is 1 by definition. – Jens May 07 '17 at 20:11
  • @Jens I am just trying to help OP get the basics..i am not trying to compile a programm here! – Sarriman May 07 '17 at 20:15
  • @AbhishekPandey I will update my original post..feel free to vote me , or ask more if you like!! – Sarriman May 07 '17 at 20:32
  • @Diaman , I'm looking forward to your update on the post. Would really like to know what has been done by those two statements. Thanks. – Abhishek Pandey May 07 '17 at 20:39
  • 2
    `char *str2=(char)0;` is very odd code. The `0` is an `int`, then it is casts to a `char` (why?), then converted to a `char *` due to the assignment. – chux - Reinstate Monica May 08 '17 at 00:00
  • Pointers are just ways of pointing into memory. `char* pointer=(char)0;` just initializing this pointer to point in null. Thus at "nothing" since its a pointer to characters therefore a string(don't forget that in C a string terminates in NULL (0 OF ASCII). – Sarriman May 08 '17 at 08:17
  • @Chux in a few words, the point you are wondering about, does nothing more but to initialize the pointer and point it to NULL (0 in ASCII, so (char)0, or if you like `\0` – Sarriman May 08 '17 at 09:35
  • 1
    @Diaman `char *str2 = NULL;` would be most clear. In C, `NULL` is the _null pointer constant_, not the _null character_ at the end of a string which `char *str2=(char)0` employs. Although `NULL` and `(char)0` can both have a _value_ of zero - so code "works", they differ in type. `char *str2=(char)0;` conveys an "novel" understanding of `NULL`, and the _null character_. – chux - Reinstate Monica May 08 '17 at 13:59