fgets "Access violation writing location 0xCCCCCCCC." error - c

Error: Unhandled exception at 0x60092A8D (msvcr110d.dll) in C_Son60.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC.
When below code executed this error code is given.(Compiles successfully)
Where is my mistake?
#include <stdio.h>
int i;
int main(void){
char *names[3];
//get the names of the cities
puts("Enter names of cities");
for (i = 0; i < 3; i++)
{
fgets( names[i], 99, stdin);
}
//print entered names
for (i = 0; i < 3; i++)
{
printf("%s", *names[i]);
}
getch();
}

You need to allocate memory to which the char pointers point to before you read them in
for instance:
for (i = 0; i < 3; i++)
{
names[i] = malloc(200);
fgets( names[i], 99, stdin);
}

2 things:
you need to allocate the strings you created- you can do it with malloc(100 * sizeof(char))
when printing you do *names[i] which means - **(names + i).
all you need is names[i]
use the code:
#include <stdio.h>
int i;
int main(void){
char *names[3];
//get the names of the cities
puts("Enter names of cities");
for (i = 0; i < 3; i++)
{
names[i] = (char *)malloc(100 * sizeof(char));
fgets( names[i], 99, stdin);
}
//print entered names
for (i = 0; i < 3; i++)
{
printf("%s", names[i]);
}
getch();
}

You must allocate your memory before storing anything into it. When you need to allocate an array of elements, and you do not know the number of elements at compile time, you must use malloc() to allocate them.
Don't forget to free your dynamically allocated memory later in order to avoid memory leaks!

Related

Loop of sprintf only outputing final looped value

I have an char* array. I loop through the correct index of the array to put numbers.
However, it seems that the value placed in the index is wrong. It seems to only store the last call to sprintf.
For instance, if I want the numbers 0, 1, 2, 3. However, it seems to return 3, 3, 3, 3.
I have placed a printf statement to see if there is an error, but it produces the correct numbers. I assume there must be a weird error when using sprintf with an array.
char* printArray[12];
for (int i = 1; i < 12+1; i++) {
char *printVal;
char temp[10];
sprintf(temp, "%d", i-1);
printVal = temp;
printf("%s\n", printVal);
printArray[i-1] = printVal;
}
for (int i = 0; i < 12; i++) {
printf("%s\n", printArray[i]);
}
This is a simplified version. This produces the error.
I have attempted to use strcpy but that results in the same error.
The problem is that the memory for temp goes away when you leave each iteration of the for loop, so you can't save pointers to temp into printArray.
You need to make a dynamic copy of temp so you can save it outside the loop.
printArray should be an array of strings, not pointers, then you can use strcpy() to copy them.
char *printArray[12];
for (int i = 1; i < 12+1; i++) {
char temp[10];
sprintf(temp, "%d", i-1);
printf("%s\n", temp);
printArray[i-1] = strdup(temp);
}
for (int i = 0; i < 12; i++) {
printf("%s\n", printArray[i]);
}
If you don't have strdup() available, it's simple:
char *my_strdup(const char *s) {
char *new = malloc(strlen(s)+1);
if (new) {
strcpy(new, s);
}
return new;
}
Undefined behavior (UB)
printArray[i-1] = printVal; repeatedly assigns the address of local object char temp[10];.
Later code attempts to print the data in this common, now invalid, address: result UB.
Instead of copying a pointer, copy the contents into memory.
// char* printArray[12];
#define INT_STRING_SIZE 12
char printArray[12][INT_STRING_SIZE];
...
for (int i = 0; i < 12; i++) {
snprintf(printArray[i], sizeof printArray[i], "%d", i);
}
If code must remain as char* printArray[12];, allocate memory.
for (int i = 0; i < 12; i++) {
char temp[INT_STRING_SIZE];
int len = snprintf(temp, sizeof temp, "%d", i);
printArray[i] = malloc(len + 1);
// Check for allocation omitted brevity.
memcpy(printArray[i], temp, len + 1);
// or
strcpy(printArray[i], temp);
}
And free the memory when done.

How to create an array of strings of unknown size?

I'm trying to understand how can I create a C program that declares an "array of strings" whose size is unknown at the time of declaration. This is what I've got so far:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i;
char** words;
printf("How many strings you want to input? \n");
scanf("%d", &n);
words = malloc(sizeof(char*) * n);
for (i = 0; i < n; i++) {
printf("Input your %d string: ", i + 1);
scanf("%s", words[i]);
}
for (i = 0; i < n; i++) {
printf("%s\n", words[i]);
}
return 0;
}
The program compiles, but I get a Segmentation fault error.
You only allocated memory for the pointer to the strings, but not for the strings themselves. Attempting to store strings at non-allocated memory invokes undefined behavior.
The pointer are just pointer. You cannot store strings in them. You need to reserve memory for where the pointer should point to.
#define STR_SIZE 100 // max length of a string (incl. null terminator)
printf("How many strings you want to input? \n");
if (scanf("%d", &n) != 1)
{
fputs("Error at input", stderr);
// further error routine.
}
// allocate memory for the pointer to the strings.
words = malloc(sizeof(*words) * n);
if (!words)
{
// error routine if the memory allocation failed.
perror("malloc");
exit(EXIT_FAILURE);
}
// allocate memory for the strings themselves.
for (int i = 0; i < n; i++)
{
words[i] = malloc(sizeof(**words) * STR_SIZE);
if (!words[i])
{
// error routine if the memory allocation failed.
perror("malloc");
exit(EXIT_FAILURE);
}
}
Side notes:
Always check the return of memory-management functions if an error happened at the allocation! Same goes for input operations such as scanf().
Note that using sizeof(*words) and sizeof(**words) instead of sizeof(char*) and sizeof(char) is more safe for the case your code changes.
You did not allocate the memory properly for individual char pointer words[i].
This was ok - you allocated memory for the pointer to pointer to char words:
words = malloc(sizeof(char*) * n);
But then you haven't allocated for individual pointers of that words yet. To do so, you need to provision how much buffer to for individual word. As an example, if each word is 100 char, then:
for (i = 0; i < n; i++)
{
printf("Input your %d string: ", i + 1);
words[i] = malloc(sizeof(char) * 100); //<--
scanf("%s", words[i]);
}
Also remember to free the buffer once you're done.
for (int i=0; i<n; ++i) {
free(words[i]);
}
free(words);
return 0;

Cant get first character in array of strings

I want to get first char character of each string. Here a example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
int size = 2;
char** text = (char**) malloc(sizeof(char*) * size);
for(int i = 0; i < size; ++i) {
char buf[80];
fgets(buf, 80, stdin);
text[i] = (char*)malloc(strlen(buf));
strcpy(text[i], buf);
}
for(int i = 0; i < strlen(text[i]); ++i) {
printf("%c ", text[i][0]);
}
}
In last for loop, program falls in Segmentation fault. I dont know why.
The strlen function returns the number of characters in the given string not including the terminal nul character; however, the strcpy function copies all characters including that terminating nul!
So, your allocation for text[i] is not quite big enough and, by writing beyond the buffer's bounds, you are getting undefined behaviour.
Add an extra character to the malloc call:
for(int i = 0; i < size; ++i) {
char buf[80];
fgets(buf, 80, stdin);
text[i] = malloc(strlen(buf) + 1); // Need space for the terminal nul!
strcpy(text[i], buf);
}
Or, more simply, use the strdup function, which achieves the same result as your malloc and strcpy in one fell swoop:
for(int i = 0; i < size; ++i) {
char buf[80];
fgets(buf, 80, stdin);
text[i] = strdup(buf);
}
Either way, don't forget to call free on all the buffers you allocate.
EDIT: You are also using the wrong 'limit' in your final output loop; this:
for(int i = 0; i < strlen(text[i]); ++i) { // strlen() is not the # strings
printf("%c ", text[i][0]);
}
Should be:
for(int i = 0; i < size; ++i) { // "size" is your number of strings!
printf("%c ", text[i][0]);
}

Array filling itself with only the last user entered inputed string

I m trying to make a piece of code that prompts the user for a number of string, n, dynamically allocates an array of n strings, and then prompts the user to enter n strings.
The problem I am having is the array is only showing itself being filled with the last string the user entered.
Example:
Program prompts user for n
User enters 3.
User enters "test1" for the first element in the array
User enters "test2" for the second element in the array
User enters "test3" for the third element in the array
I go to print the contents of the array, and it says each element is "test3"
Here is the code:
(flush_buffer() and strip_newline() are functions I wrote that are unimportant to the problem I am having)
printf("How many strings?\n");
scanf("%d", &max_strings);
flush_buffer();
string_array = (char**) malloc(max_strings * sizeof(char*));
for(i = 0; i < max_strings; i++)
{
scanf("%s", temp);
strip_newline(temp);
string_array[i] = temp;
printf("string_array[%d] is: %s\n", i, string_array[i]);
}
for(i = 0; i < max_strings; i++)
{
printf("i: %d\n", i);
printf("string_array[%d] is: %s\n", i, string_array[i]);
}
Any ideas on what I am missing here?
With the assignment
string_array[i] = temp;
you make all pointers in string_array point to the same place.
I suggest you use strdup to duplicate the string instead:
string_array[i] = strdup(temp);
Of course, this means you have to free all strings in the collection.
When you assign the strings:
string_array[i] = temp;
you just store a pointer of the temporary buffer in each string, which will be overwritten after the next string is read. In other words, all of your strings have the same value, namely temp, which has the contents of the last string read.
If you want to store your strings, you must allocate memory for string_array[i] and then copy the contents with strcpy. Alternatively, you can use a shortcut:
string_array[i] = strdup(temp);
Note that strdup allocates memory internally that you must free() at some point.
you can use this code:
int max_strings;
printf("How many strings?\n");
scanf("%d", &max_strings);
//allocate memory
char **string_array = (char**) malloc(max_strings * sizeof(char*));
for (int i = 0; i < max_strings; i++)
{
string_array[i] = (char*)malloc(sizeof(char) * 50);
}
for(int i = 0; i < max_strings; i++)
{
scanf("%s", string_array[i]);
printf("string_array[%d] is: %s\n", i, string_array[i]);
}
for(int i = 0; i < max_strings; i++)
{
printf("i: %d\n", i);
printf("string_array[%d] is: %s\n", i, string_array[i]);
}
//free memory
for (int i = 0; i < max_strings; i++)
{
free(string_array[i]);
}
free(string_array);

Getting words from text file to an array

My text file is formated like that:
my.txt
Red
Green
Blue
Yellow
I'm tring to get words like that:
typedef char * string;
main(){
int i;
string array[4];
FILE *my;
my = fopen("my.txt","r");
for(i = 0; i < 4; i++)
fscanf(data, "%s", &array[i]);
fclose(my);
}
When I try to print the array there is an error. What's wrong with my code and how can I fix it?
You'll need to allocate memory for your null-terminated strings.
At the moment you are only allocating memory for 4 char *, but these pointers are uninitialized and therefor will result in UB (undefined behavior) when you try to write data to the memory pointed to by them.
Working example snippet
The use of "%127s" in the below snippet is to prevent us writing outside the bounds of the allocated memory. With the format-string in question we will at the most read/write 127 bytes + the null-terminator.
Please remember that further error checks should be implemented if this is to be used in "real life".
Check to see that file_handle is indeed valid after attempt to open the file
Check to see that malloc did indeed allocate requested memory
Check to see that fscanf read the desired input
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int
main (int argc, char *argv[])
{
int i;
char * lines[4];
FILE *file_handle = fopen ("my.txt", "r");
for (i =0; i < 4; ++i) {
lines[i] = malloc (128); /* allocate a memory slot of 128 chars */
fscanf (file_handle, "%127s", lines[i]);
}
for (i =0; i < 4; ++i)
printf ("%d: %s\n", i, lines[i]);
for (i =0; i < 4; ++i)
free (lines[i]); /* remember to deallocated the memory allocated */
return 0;
}
output
0: Red
1: Green
2: Blue
3: Yellow
You try to read some data, but you don't have anywhere to put it. All you have is 4 pointers, pointing to god knows where and you are trying to write into it!
There are many ways to do this:
You know the bound to the size of the data:
#include <stdio.h>
#define MAX_CHARS 20
typedef char string[MAX_CHARS+1]; // leave one space for '\0'
main(){
int i;
string array[4];
FILE *my;
my = fopen("my.txt","r");
for(i = 0; i < 4; i++)
fscanf(data, "%s", array[i]); // no need for & with %s
fclose(my);
}
Assume a bound to the size of the data, and ignore the rest of the strings (if it was too big):
#include <stdio.h>
#define MAX_CHARS 20
#define MAX_CHARS_STR "20" // there are better ways to get this
typedef char string[MAX_CHARS+1];
main(){
int i;
string array[4];
FILE *my;
my = fopen("my.txt","r");
for(i = 0; i < 4; i++){
fscanf(data, "%"MAX_CHARS_STR"s", &array[i]); // read at most 20 chars for the string
ungetc('x', data); // append one character to make sure we don't hit space
fscanf(data, "%*s"); // ignore whatever is left of string
}
fclose(my);
}
Read the file twice, first time find out the sizes of each string (or the maximum size, for simplicity), then allocate memory for the strings (using malloc). Then read the file again and this time actually store the strings:
#include <stdio.h>
typedef char *string;
main(){
int i;
string array[4];
int cur_size = 0;
FILE *my;
my = fopen("my.txt","r");
for(i = 0; i < 4; i++){
fscanf(data, "%*s%n", &cur_size);
array[i] = malloc((cur_size+1)*sizeof(*array[i]));
}
fclose(my);
my = fopen("my.txt","r");
for(i = 0; i < 4; i++){
fscanf(data, "%s", array[i]);
}
fclose(my);
// and when done:
for(i = 0; i < 4; i++){
free(array[i]);
}
}
Read from the input chunk by chunk. For each string, if input string was not finished yet resize the memory allocated for the string (increase its size), read another chunk and check again. Method 3 is faster though and I recommend it, but just so you know, this is basically what happens in C++'s string.
Since all the other answers told you what you did wrong but not how to fix it. Here
typedef char * string;
#define LEN 100 //long enough for your line
main(){
int i;
string array[4];
for(i = 0; i < 4; i++) {
if((array[i] = (char *)(malloc(sizeof(char) * LEN))) == NULL) {
printf("malloc failed");
return 1;
}
}
FILE *my;
my = fopen("my.txt","r");
for(i = 0; i < 4; i++)
fscanf(data, "%s", &array[i]);
fclose(my);
}
And like they said you made space for the pointers but not for what the pointers point to.

Resources