2D dynamic allocation in C error when incrementing the pointer - c

I wanted to allocate a string array dynamically , the program is supposed to ask the user for characters and collect them in the first string in the array till letter 'q' is entered then the program starts adding the characters to the second line and so on.
When I print the characters memory location it seems like each character takes two memory cells instead of one though I increment it only once.
Here is the source code to my program
#include <stdio.h>
void main()
{
char** txt;
char* baseAddress;
txt = (char **)malloc(5*sizeof(char*));
*txt = (char *)malloc(20*sizeof(char));
baseAddress = *txt;
while (*(*txt) != 'q')
{
(*txt)++;
scanf("%c", (*txt));
printf("%p\r\n", (*txt));
}
*txt = '\0';
printf("%p", baseAddress);
free(baseAddress);
free(txt);
}
the output is like this
>j
>0x9e12021
>0x9e12022
>s
>0x9e12023
>0x9e12024
>
I think there may be something wrong with the pointers.
How do I go about accomplishing this? and sorry for the bad english

What exacty you code do :
+----------------------------------------------+
| +--------------------------------------+ |
| txt|*txt |*txt+1 |*txt+2 |*txt+3 |*txt+4 | |
| +--------------------------------------+ |
| ^ ^ no memory alloc ^ |
| | |_______not used_______| |
| +----+ |
|*txt |____| <------------------------------+---you never give a value here,
| +1 |____| <--j |
| +2 |____| <-- '\n' |
| +3 |____| <--s |
| +4 |____| <-- '\n' |
| . . |
| . . |
| . ____ |
| +19 |____| |
+----------------------------------------------+
So you need :
re-write you while loop and deal with the '\n'
when user type q , alloc new string memory and collect user input .
Suggust:
In you fisrt string
Use txt[0] instead of *txt , use txt[0][i] and i++ instead of **txt and (*txt)++ .
Hope can help. :-)

You are forgetting about the newline character.
For instance, you are probably imagining your input to be "js". However, since you are hitting the enter key, it is actually "j\ns\n".
So, you are entering two characters at a time, and it is reading two characters at a time. Your code is behaving just as it should.

Related

Why does accessing an array of pointers de-references the pointer of the pointer?

I cannot understand this unexpected C behavior where printing argv[0] prints ./a.out instead of the actual content of argv[0] which should be a memory address because argv is an array of pointers.
If I create an array called char name[] = "hello" then I would expect to see h at name[0] and if char * argv[] holds, for example 3 pointers (memory addresses) then logically argv[0] should be a memory address.
My reasoning is that if I wanted to access the actual content of the memory address that argv[0] points to I should need to do *(argv[0]). What is happening here? Is C doing some kind of magic here?
+------+------+------+---+---+----+
| h | e | l | l | o | \0 |
+------+------+------+---+---+----+
^---- name[0] = h
+------+------+------+
| 0xA7 | 0xCE | 0xC4 |
+------+------+------+
^---- argv[0] = should be 0XA7 (the value of `argv[0]`,
not the value it points to
#include <stdio.h>
int main(int argc, char * argv[]) {
char name[] = "hello";
printf("%c \n", name[0]); // expected h
printf("%s \n", argv[0]); // expected 0xA7 (but got ./a.out instead)
}
$ gcc main.c
$ ./a.out arg1 arg2 arg3
My reasoning is that if I wanted to access the actual content of the memory address that argv[0] points to I should need to do *(argv[0]). What is happening here?
printf is doing the dereferencing. When passed "%s" and a pointer (address), printf doesn't print the address. It prints what's at the address. Specifically, it prints ptr[0], ptr[1], ptr[2] etc until a zero is encountered.
(Keep in mind that ptr[i] is identical to *(ptr+i). I'm going to use the former since it's cleaner.)
Let's start with a simpler example.
char *name = "hello";
printf( "%s", name );
name
+-------------------+ +-----+-----+-----+-----+-----+-----+
| [Some address 1] -------->| 'h' | 'e' | 'l' | 'l' | 'o' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+-----+
Passing "%s", name passes the address of an array containing %s␀ and the address contained by name ("[Some address 1]"). The latter is the address of an array containing hello␀.
This tells printf to print name[0] (h), name[1] (e), name[2] (l), etc until a zero is encountered.
Now let's look at your case.
argv
+-------------------+ +-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 2] -------->| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
+-------------------+ +-------------------+ -----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 4] -------->| 'a' | 'r' | 'g' | '1' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| [Some address 5] -------->| 'a' | 'r' | 'g' | '2' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| [Some address 6] -------->| 'a' | 'r' | 'g' | '3' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| NULL |
+-------------------+
or just
argv[0]
+-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
Passing "%s", argv[0] passes the address of an array containing %s␀ and the address contained by argv[0] ("[Some address 3]"). The latter is the address of an array containing ./a.out␀.
This tells printf to print argv[0][0] (.), argv[0][1] (/), argv[0][2] (.), etc until a zero is encountered.
%s tells printf “Load characters from the address you are passed and print the characters from there until you find a null character.”
With %s, printf does not print or format the address it is passed. It uses the address to access memory.
For an array declared like:
char name[] = "hello";
the expression name[0] has the type char and by using the conversion specifier c in the call of printf:
printf("%c \n", name[0]);
the first element of the array is outputted as a character.
This declaration of an array:
char * argv[]
that is used as a parameter declaration is adjusted by the compiler to the declaration:
char **argv
and the expression argv[0] has type char *.
The conversion specifier s is designed to output strings pointed to by corresponding arguments like this:
printf("%s \n", argv[0]);
argv[0] points to a string that contains the name of the program that runs.
If you want to output the expression as an address you need to write:
printf("%p \n", ( void * )argv[0]);
To make it more clear consider this statement:
printf( "%s\n", "Hello" );
Its output I think you are expecting is:
Hello
The string literal has the type char[6]. But using as an expression in the call of printf it is implicitly converted to pointer to its first element of the type char *.
So the second argument of the call of printf has the type char * the same way as in the call:
printf("%s \n", argv[0]);
where the second expression also has the type char *.

Does a 1D array work as a list of strings, or a single string?

#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[10];
for(i=0;i<10;i++)
{
scanf("%s",a);// >how this line is working in memory.
}
return 0;
}
In the above code, I would like to know how the string is saved in memory, since I have initialised it as a 1D character array, but does the array work as a list of strings, or a single string? Why?
In C, a string is a sequence of character values terminated by a 0-valued character - IOW, the string "Hello" is represented as the character sequence 'H', 'e', 'l', 'l', 'o', 0. Strings are stored in arrays of char (or wchar_t for wide strings):
char str[] = "Hello";
In memory, str would look something like this:
+---+
str: |'H'| str[0]
+---+
|'e'| str[1]
+---+
|'l'| str[2]
+---+
|'l'| str[3]
+---+
|'o'| str[4]
+---+
| 0 | str[5]
+---+
It is possible to store multiple strings in a single 1D array, although almost nobody does this:
char strs[] = "foo\0bar";
In memory:
+---+
strs: |'f'| strs[0]
+---+
|'o'| strs[1]
+---+
|'o'| strs[2]
+---+
| 0 | strs[3]
+---+
|'b'| strs[4]
+---+
|'a'| strs[5]
+---+
|'r'| strs[6]
+---+
| 0 | strs[7]
+---+
The string "foo" is stored starting at strs[0], while the string "bar" is stored starting at strs[4].
Normally, to store an array of strings, you'd either use a 2D array of char:
char strs[][MAX_STR_LEN] = { "foo", "bar", "bletch" };
or a 1D array of pointers to char:
char *strs[] = { "foo", "bar", "bletch" };
In the first case, the contents of the string are stored within the strs array:
+---+---+---+---+---+---+---+
strs: |'f'|'o'|'o'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'a'|'r'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In the second, each strs[i] points to a different, 1D array of char:
+---+ +---+---+---+---+
strs: | | strs[0] ------> |'f'|'o'|'o'| 0 |
+---+ +---+---+---+---+
| | strs[1] ----+
+---+ | +---+---+---+---+
| | strs[2] -+ +-> |'b'|'a'|'r'| 0 |
+---+ | +---+---+---+---+
|
| +---+---+---+---+---+---+---+
+----> |'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In your code, a can (and is usually intended to) store a single string that's 9 characters long (not counting the 0 terminator). Like I said, almost nobody stores multiple strings in a single 1D array, but it is possible (in this case, a can store 2 4-character strings).
char a[10];
You've allocated 10 bytes of the stack for a. But right now, it contains garbage because you never gave it a value.
Scanf doesn't know any of this. All it does is copy bytes from the standard input into a, ignorant of its size.
And why are you doing a loop 10 times? You will overwrite a each loop iteration, so you'll only have the value from the final time.
A string is per definition a null-terminated character array. So every character array becomes a string as soon as it contains a \0 somewhere, defining the end of that string.
In memory the string is just a bunch of bytes laying (for simplicity but not necessarily) in sequence. Take the string "Hello" for example
+---+---+---+---+---+---+
| H | e | l | l | o | \0|
+---+---+---+---+---+---+
Your array char a[10] is pointing to the beginning of such a memory location ('H' in the example) with enough space to store 10 characters.
By using scanf you are storing an string (character sequence + terminating \0) in that buffer (over and over again). scanf stores the characters in there and adds a terminating \0 to the element after the last one written to. This allows you to safely store any character sequence that is at most 9 characters long, since the 10th character needs to be the \0
Does a 1D array work as a list of strings, or a single string?
quite broad question.
char a[10]; declared table a which has a size of 10 the char elements
char *a[10]; declared table a which has a size of 10 char * elements which can possible point to the string (when you allocate memory for it and copy the valid C string)
In your code:
'scanf("%s",a);' a means the address of the first element of the array. So scanf writes data there, every time overwriting the previous content. If your scanf-ed input will need more 10 elements (including trailing 0) to be stored, you will get an UB and very possible SEGFAUT
You are over-writing same buffer in loop 10 times, which means buffer will contain data entered in last reading and previous 9 strings will be lost.
Also entering more than 9 characters would cause buffer overflow which would invoke undefined behavior.
You should limit number of characters scanned from input buffer and then clear the rest of the buffer. (Not fflush(stdin);)
scanf("%9s",a);
Does a 1D array work as a list of strings, or a single string?
If its terminated with null character then yes, its string, like this. And a is the address of first element.
+---+---+---+---+---+---+----+
| S | t | r | i | n | g | \0 |
+---+---+---+---+---+---+----+
a a+1 a+2
And if you pass this array ie. to printf(), he will print all characters until he reach \0.
If you would like to read list of strings, you have to declare 2D array or pointer-to-pointer-to-char and allocate enough memory for pointers.
int c;
char a[10][10];
for(i=0;i<10;i++)
{
scanf("%9s",a[i]);
while ((c = getchar()) != '\n' && c != EOF) ;
}

Issue With Comparing Strings In C

I'm trying to compare a string with another string and if they match I want the text "That is correct" to output but I can't seem to get it working.
Here is the code:
int main ()
{
char * password = "Torroc";
char * userInput;
printf("Please enter your password: ");
scanf("%s", userInput);
if (strcmp(password, userInput) == 0) {
printf("That is correct!");
}
}
In your code, userInput pointer does not have provision to hold the string that you are about to pass using the scanf call. You need to allocate space for the cstring userInput in your stack, before you try to save/assign any string to it. So...
You need to change the following code:
char * userInput;
to:
char userInput[200];
Here, 200 is just an arbitrary value. In your case, please select the max. length of the string + 1 for the (\0).
When you enter characters you need to store the characters somewhere.
char* userInput;
is an uninitialized pointer.
So first you declare an array for your input
char userInput[128];
Now when reading from the keyboard you need to make sure the user does not enter more characters than 127 + one for \0 because it would overwrite the stack so best way to read from the keyboard is to use fgets, it also good to check the return value, if the user simply pressed ENTER without writing anything fgets returns NULL.
if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
Now you have the string that the user entered plus the end of line character. To remove it you can do something like
char* p = strchr(userInput,'\n');
if ( p != NULL ) *p = '\0';
Now you can compare the strings
if (strcmp(password, userInput) == 0) {
puts("That is correct!");
}
When you think about "a string" in C, you should see it as an array of char's.
Let me use the identifier s instead of userInput for brevity:
0 1 2 3 4 5 9
+---+---+---+---+---+---+-- --+---+
s -> | p | i | p | p | o | \0| ... | |
+---+---+---+---+---+---+-- --+---+
is what
char s[10] = "pippo";
would create.
In other words, it's a block of memory where the first 6 bytes have been initialized as shown. There is no s variable anywhere.
Instead, declaring a char * like in
char *s;
would create a variable that can hold a pointer to char:
+------------+
s| 0xCF024408 | <-- represent an address
+------------+
If you think this way, you notice immediately that doing:
scanf("%s",s);
only make sense in the first case, where there is (hopefully) enough memory to hold the string.
In the second case, the variable s points to some random address and you will end up writing something into an unknown memory area.
For completeness, in cases like:
char *s = "pippo";
you have the following situation in memory:
0 1 2 3 4 5
+---+---+---+---+---+---+ Somewhere in the
0x0B320080 | p | i | p | p | o | \0| <-- readonly portion
+---+---+---+---+---+---+ of memory
+------------+ a variable pointing
s| 0x0B320080 | <-- to the address where
+------------+ the string is
You can make s pointing somewhere else but you can't change the content of the string pointed by s.

Alphabetical comparison of two strings in C

My programming experience is extremely scattered and I can't seem to find the answer to what I hope is a simple question. I had an assignment last week that I didn't properly finish and it's bugging me to death.
I was supposed to compare two strings alphabetically without using strcmp and find out which string is alphabetically first via a function using pointers.
int strcmp373(char *str1, char *str2) {
while(*str1 != '\0')
{
str1++;
}
while(*str2 != '\0')
{
str2++;
}
if(*str1 == *str2)
}
This is my horrible attempt, my thought process being to use the null terminated value. I was hoping I could get some insight and explain how it works?
Here's a copy of the assignment specifications for reference.
Write a function called strcmp373, which compares two strings in precisely the same way that strcmp does in the C library . This time, please use "pointer syntax" in writing this function. That is, the [ ] operator should not be used at all when referring to particular characters in string1 and string2; instead, all parameters and local variables should be declared as pointers (using the * symbol). Please be sure that you emulate the strcmp C function. Note that strcmp returns 0 if the two strings are equal, even though 0 normally means false in C. The sign of other return values matters is used to indicate in what way the strings are not the same, but the precise return value is not important.
You may not use any of the built-in C string library functions to complete this code.
Here is the prototype of this function:
int strcmp373(char *, char *);
And here is a main function which you can use to test strcmp373.
#include <stdio.h>
#include "hw3.h" // to be discussed
int main() {
char str1[81], str2[81];
char again = 'y', newline;
while (again == 'y') {
printf("Enter a string\n");
scanf("%s", str1);
printf("Enter another string\n");
scanf("%s", str2);
int comp = strcmp373(str1, str2);
if (comp < 0)
printf("%s is alphabetically before %s\n", str1, str2);
else if (comp > 0)
printf("%s is alphabetically after %s\n", str1, str2);
else printf("%s and %s are the same\n", str1, str2);
printf("Again? (y/n)\n");
scanf("%c%c", &newline, &again);
}
}
Let's say str1 points to something that holds "abcd" and str2 points to something that holds "abc".
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
When you execute
while(*str1 != '\0')
{
str1++;
}
You move str1 until it points to the null character.
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
Similarly, when you execute
while(*str2 != '\0')
{
str2++;
}
You move str2 until it points to the null character.
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
When the while loops are done, both str1 and str2 point to a null character. Hence, *str1 == *str2 always evaluates to true.
What you need is to compare *str1 and *str2 and then increment them together if they are equal until they are not equal or you reach the end of the strings.
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
Now that you know they are not equal and 'd' is greater tha '\0' return a positive value indicating the LHS is alphabetically greater than the RHS.
That logic can be implemented using:
while ( *str1 != '\0' && *str1 == *str2 )
{
++str1;
++str2;
}
return (*str1 - *str2);
if(*str1 == *str2)
You have an if statement with no body in your code excerpt.
Apart from that your program is counting the amount of characters in the character array passed to that function. This won't really achieve your goal.
Lets call each char array a word. What you want to do is find which 'word' comes first in the alphabet. I suggest looking at an ASCII table.
Each letter in either word has a corresponding ASCII number value. If you can figure out how to access the number value of each of these letters, you can compare the strings and the lower value will be higher up in the alphabet.
Unless they are capitalized. That will require a little more work. Here is an ASCII table where you can see the difference.
This will get you started with figuring out how to get the ASCII value of these letters

Reading file in C

I'm reading a file in my C program and comparing every word in it with my word, which is entered via command line argument. But I get crashes, and I can't understand what's wrong. How do I track such errors? What is wrong in my case?
My compiler is clang. The code compiles fine. When running it says 'segmentation fault'.
Here is the code.
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* temp = argv[1];
char* word = strcat(temp, "\n");
char* c = "abc";
FILE *input = fopen("/usr/share/dict/words", "r");
while (strcmp(word, c))
{
char* duh = fgets(c, 20, input);
printf("%s", duh);
}
if (!strcmp (word, c))
{
printf("FOUND IT!\n");
printf("%s\n%s", word, c);
}
fclose(input);
}
The issue here is that you are trying to treat strings in C as you might in another language (like C++ or Java), in which they are resizable vectors that you can easily append or read an arbitrary amount of data into.
C strings are much lower level. They are simply an array of characters (or a pointer to such an array; arrays can be treated like pointers to their first element in C anyhow), and the string is treated as all of the characters within that array up to the first null character. These arrays are fixed size; if you want a string of an arbitrary size, you need to allocate it yourself using malloc(), or allocate it on the stack with the size that you would like.
One thing here that is a little confusing is you are using a non-standard type string. Given the context, I'm assuming that's coming from your cs50.h, and is just a typedef to char *. It will probably reduce confusion if you actually use char * instead of string; using a typedef obscures what's really going on.
Let's start with the first problem.
string word = strcat(argv[1], "\n");
strcat() appends the second string onto the first; it starts from the null terminator of the first string, and replaces that with the first character of the second string, and so on, until it reaches a null in the second string. In order for this to work, the buffer containing the first string needs to have enough room to fit the second one. If it does not, you may overwrite arbitrary other memory, which could cause your program to crash or have all kinds of other unexpected behavior.
Here's an illustration. Let's say that argv[1] contains the word hello, and the buffer has exactly as much space as it needs for this. After it is some other data; I've filled in other for the sake of example, though it won't actually be that, it could be anything, and it may or may not be important:
+---+---+---+---+---+---+---+---+---+---+---+---+
| h | e | l | l | o | \0| o | t | h | e | r | \0|
+---+---+---+---+---+---+---+---+---+---+---+---+
Now if you use strcat() to append "\n", you will get:
+---+---+---+---+---+---+---+---+---+---+---+---+
| h | e | l | l | o | \n| \0| t | h | e | r | \0|
+---+---+---+---+---+---+---+---+---+---+---+---+
You can see that we've overwritten the other data that was after hello. This may cause all kinds of problems. To fix this, you need to copy your argv[1] into a new string, that has enough room for it plus one more character (and don't forget the trailing null). You can call strlen() to get the length of the string, then add 1 for the \n, and one for the trailing null, to get the length that you need.
Actually, instead of trying to add a \n to the word you get in from the command line, I would recommend stripping off the \n from your input words, or using strncmp() to compare all but the last character (the \n). In general, it's best in C to avoid appending strings, as appending strings means you need to allocate memory and copy things around, and it can be easy to make mistakes doing so, as well as being inefficient. Higher level languages usually take care of the details for you, making it easier to append strings, though still just as inefficient.
After your edit, you changed this to:
char* temp = argv[1];
char* word = strcat(temp, "\n");
However, this has the same problem. A char * is a pointer to a character array. Your temp variable is just copying the pointer, not the actual value; it is still pointing to the same buffer. Here's an illustration; I'm making up addresses for the purposes of demonstration, in the real machine there will be more objects in between these things, but this should suffice for the purpose of demonstration.
+------------+---------+-------+
| name | address | value |
+------------+---------+-------+
| argv | 1000 | 1004 |-------+
| argv[0] | 1004 | 1008 | --+ <-+
| argv[1] | 1006 | 1016 | --|---+
| argv[0][0] | 1008 | 'm' | <-+ |
| argv[0][1] | 1009 | 'y' | |
| argv[0][2] | 1010 | 'p' | |
| argv[0][3] | 1011 | 'r' | |
| argv[0][4] | 1012 | 'o' | |
| argv[0][5] | 1013 | 'g' | |
| argv[0][6] | 1014 | 0 | |
| argv[1][0] | 1016 | 'w' | <-+ <-+
| argv[1][1] | 1017 | 'o' | |
| argv[1][2] | 1018 | 'r' | |
| argv[1][3] | 1019 | 'd' | |
| argv[1][4] | 1020 | 0 | |
+------------+---------+-------+ |
Now when you create your temp variable, all you are doing is copying argv[1] into a new char *:
+------------+---------+-------+ |
| name | address | value | |
+------------+---------+-------+ |
| temp | 1024 | 1016 | --+
+------------+---------+-------+
As a side note, you also shouldn't ever try to access argv[1] without checking that argc is greater than 1. If someone doesn't pass any arguments in, then argv[1] itself is invalid to access.
I'll move on to the next problem.
string c = "abc";
// ...
char* duh = fgets(c, 20, input);
Here, you are referring to the static string "abc". A string that appears literally in the source, like "abc", goes into a special, read-only part of the memory of the program. Remember what I said; string here is just a way of saying char *. So c is actually just a pointer into this read-only section of memory; and it has only enough room to store the characters that you provided in the text (4, for abc and the null character terminating the string). fgets() takes as its first argument a place to store the string that it is reading, and its second the amount of space that it has. So you are trying to read up to 20 bytes, into a read-only buffer that only has room for 4.
You need to either allocate space for reading on the stack, using, for example:
char c[20];
Or dynamically, using malloc():
char *c = malloc(20);
First problem I see is this:
string word = strcat(argv[1], "\n");
You are adding characters to the end of a buffer here.
A buffer allocated for you by the runtime enviroment, that you should consider read only.
EDIT
I'm afraid your change to the code still has the same effect.
char* temp = argv[1];
Has temp pointing to the same buffer as argv[1].
You need to allocate a buffer the proper size, and use it.
char* temp = (char*)malloc(sizeof(char) * (strlen(argv[1]) + 2));
The +2 is for the adding \n and \0 at the end.
Than you do this:
strcpy(temp, argv[1]);
strcat(temp,"\n");
The code is rather flawed. Another one:
char* duh = fgets(c, 20, input);
Here you define a pointer to char, do not initialize it (hence it contains a random value) and then you write up to 20 bytes to the address pointed to by the random data. If you're lucky you just get a cash. If not, you overwrite some other important data. Fortunately most of the systems in use today won't let you access address space of another program, so the code wreaks havoc only on itself.
The line in question could look like:
#define BUFFERSIZE 1024
...
while (reasonable condition) {
char *duh = malloc(BUFERSIZE);
if (NULL == duh) { /* not enough memory - handle error, and exit */
}
duh = fgets(duh, BUFFERSIZE, input);
if (NULL == duh) { /* handle error or EOF condition */
} else { /* check that the line is read completely,
i.e. including end-of-line mark,
then do your stuff with the data */
}
free (duh);
}
Of course, you can allocate the buffer only once (outside of the loop) and reuse it. The #define makes it easy to adjust the maximum buffer size.
Alternatively, on recent systems, you can use getline(), which is able to allocate a buffer of appropriate size for you. That you must free() at the end of the loop.
If you are on Linux/BSD, use man (e.g. man fgets) to get information on the functions, otherwise resort to internet or a decent book on C for documentation.
First, My C knowledge is old, so I'm not sure what a string is. Either way, it's helpful, but not absolutely required to have a nice pre-zeroed buffer in which to read contents of the file. So whether you zero word or do something like the following, zero the input first.
#define IN_BUF_LEN 120
char in_buf[IN_BUF_LEN] = {0};
120 characters is a safe size, assuming most of your text lines are around 80 characters or less long.
Second, you're basing your loop of the value of a strcmp rather than actually reading the file. It might accomplish the same thing, but I'd base my while on reaching end of file.
Finally, you've declared duh a pointer, not a place to store what fgets returns. That's a problem, too. So, duh should be declared similarly to in_buf above.
Finally, you're assigning the value of argv[1] at compile time, not run-time. I can't see where that's getting you what you want. If you declare temp as a pointer and then assign argv[1] to it, you'll just have another pointer to argv[1], but not actually have copied the value of argv[1] to a local variable. Why not just use argv[1]?

Resources