Read 2D Array of String in C [duplicate] - c

This question already has answers here:
Memory overwrite problem
(4 answers)
Closed 5 years ago.
I am trying to create a 2D array of chars from some input on the keyboard.My main problem is that I don't know what I am doing wrong but I am able to get a result when I go above the length of the array. For example if I have a n x n matrix, i can print the value x[0][n] or x[0][n+1]. I just want to know what am I doing wrong as I should get an error as I am trying to go over the bound of the array.
#include <stdio.h>
#include <stdlib.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
char ** readMatrix(int m){
char **arr = safeMalloc(m*sizeof(char *));
int row;
for (row=0; row < m; row++) {
arr[row] = safeMalloc(m*sizeof(char));
}
int i,j;
for(i=0;i<m;i++){
for(j=0;j<m;j++){
scanf(" %c",&arr[i][j]);;
}
getchar();
}
return arr;
}
void printNumber(char **arr,int m){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<m;j++){
printf("%c", arr[i][j]);
}
printf("\n");
}
}
int main(int argc, char **argv)
{
int n;
scanf("%d",&n);
char** arr;
arr=readMatrix(n);
printf("%c\n",arr[0][8]);
printNumber(arr,n);
}
For example :
8
****....
****....
****....
****....
........
........
........
........
It prints the array as I expected but I can still get some funny char if I go over the bound 8.

Since C doesn't check array boundaries thats why you are not getting error but getting funny characters by accessing memory past the end of the array.

Related

Creating a 1-D array of strings from user input in C

I was attempting to create an array from user input in C. My code was as follows
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
char** my_array;
int i;
printf("%s", "Input the size of the array: ");
scanf("%d", &i);
my_array = create_array(i);
for (int m = 0; m < i; m++){
printf("%s\n", (char*)my_array[m]);
}
}
char ** create_array(int num){
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
char temp[32];
printf("Input element %d of the array: ", i);
scanf("%s", temp);
array[i] = temp;
}
for (int m = 0; m < num; m++){
printf("%s\n", array[m]);
}
printf("end of func\n");
return array;
}
I was having (possibly unrelated?) issues with segmentation faults until I replaced the declaration of temp from char *temp; to char temp[32];. I am not sure of why declaring temp as a char pointer creates the segmentation fault, if that is a simple related answer let me know, if not I will ask in another question.
However, when I run this code, upon inputting
Input the size of the array: 2
Input element 0 of the array: value0
Input element 1 of the array: value1
I get
value1
value1
end of func
Segmentation fault (core dumped)
So to me it seems like temp somehow isn't changing when the for loop executes next iteration. I'm not sure why or how that would ever happen though. I also tried changing
printf("%s\n", my_array[m]);
to
printf("%s\n", (char*)my_array[m]);
but that didn't seem to help either.
Any ideas?
Thanks
I believe this is what you're looking for. The trick is allocate the memory for the strings on the heap. Saving pointers to char temp[32]; is dangerous because it's in automatic storage. As #Spikatrix said in a comment, that memory is not guaranteed to be in a valid state between each iteration of the loop. With the data on the heap, there's a well-defined region of memory set aside and identified by the pointer returned from malloc.
There's also a lot of good reason to not use scanf. As is, your code does not do any bounds checks and can easily overwrite the 32-byte array allocated for each string.
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
int num_strings;
printf("Input the size of the array: ");
scanf("%d", &num_strings);
printf("\n");
char** my_array = create_array(num_strings);
for (int i = 0; i < num_strings; i++){
printf("%s\n", my_array[i]);
}
for (int i = 0; i < num_strings; i++) {
free(my_array[i]);
}
free(my_array);
}
char** create_array(int num) {
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
array[i] = malloc(32);
printf("Input element %d of the array: ", i);
scanf("%s", array[i]);
printf("\n");
}
printf("end of func\n");
return array;
}

why does my program print garbage values when i try using recursion?

i'm new to programming and i'm learning about recursion, i am doing exercise 4 from this page
https://www.w3resource.com/c-programming-exercises/recursion/index.php, i am trying to print the elements of the array once the value of "i" in the recursive function gets to the value of "n", however once i run the program it prints garbage values i think.my question is why does it do that? why doesn't it print the values of the array?
#include <stdio.h>
#include <stdlib.h>
void printr(int n,int i);
int main (void)
{
printf("NUMBER OF ELEMENTS:\n");
int n;
scanf("%i",&n);
printr(n,0);
}
void printr(int n,int i)
{
int arr[n];
if (i == n)
{
for (int j = 0; j < n; j++)
{
printf("%d",arr[j]);
return;
}
}
printf("element %d :\n",i+1);
int e;
//scan for input
scanf("%d",&e);
//populate array
arr[i]=e;
//do it again
printr(n,i + 1);
}
Then i solved it by passing the array defined in the mein function asan argument in the printr function
it worked but i don't understand why my first attemp didn't?
#include <stdio.h>
#include <stdlib.h>
void printr(int arr[],int n,int i);
int main (void)
{
printf("NUMBER OF ELEMENTS:\n");
int n;
scanf("%i",&n);
int arr[n];
printr(arr,n,0);
}
void printr(int arr[],int n,int i)
{
if (i == n)
{
for (int j = 0; j < n;j++)
{
printf("%d ",arr[j]);
}
printf("\n");
return;
}
printf("element %d :\n",i+1);
int e;
//scan for input
scanf("%d",&e);
//populate array
arr[i] = e;
//do it again
printr(arr,n,i + 1);
}
Thank you!
Because basic C: each invocation of printr has its own arr on the stack, initially uninitialized. And you print it without initializing it first.
When you print out the value, it isn't initialized first. When you create the variable to be printed, its pointing to a place in memory. This memory was probably freed by another program (so its up for grabs). As such, it contains "garbage" data. The way to deal with this is to initialize your values.
In order to avoid stuff like this in the future, get in the habit of setting your pointers to NULL when you don't initialize them so that your programs segfaults when your trying to read an uninitialized value.

How do I get two different outputs from adding and removing a print statement? [duplicate]

This question already has answers here:
Why is it safer to use sizeof(*pointer) in malloc
(3 answers)
What happens if I use malloc with the wrong size?
(4 answers)
Closed 2 years ago.
Here is my code with the print statement followed by its output.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int *myF(int a[],int s, int n);
int *myFunc(int x[],int size,int nnum) {
int i;
size += 1;
int *y = malloc(size);
for(i=0;i<size;i++) {
if(i==0)
*y = nnum;
else {
*(y+i) = x[i-1];
printf(" %d",*(y+i)); // <-- ***THIS THING RIGHT HERE***
}
}
return y;
}
int main (int argc, char *argv[]) {
int i;
int x[7] = {1,2,3,4,5,6,7};
int *P = myFunc(x,7,12);
for(i=0;i<8;i++) {
if(i==0) printf("\n");
printf(" %d",*(P+i));
}
return 0;
}
OUTPUT:
1 2 3 4 5 6 7
12 1 2 3 4 5 6 7
(The second matrix is what I want the code to output)
Here is my code without the print statement followed by its output.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int *myF(int a[],int s, int n);
int *myFunc(int x[],int size,int nnum) {
int i;
size += 1;
int *y = malloc(size);
for(i=0;i<size;i++) {
if(i==0)
*y = nnum;
else {
*(y+i) = x[i-1];
// printf(" %d",*(y+i)); <-- ***THIS THING RIGHT HERE*** commented out
}
}
return y;
}
int main (int argc, char *argv[]) {
int i;
int x[7] = {1,2,3,4,5,6,7};
int *P = myFunc(x,7,12);
for(i=0;i<8;i++) {
if(i==0) printf("\n");
printf(" %d",*(P+i));
}
return 0;
}
OUTPUT:
12 1 2 3 4 5 83 0
(This is not what I want...)
Can somebody please explain where this code is pulling 83 and 0 for the last two elements in the array just because I chose to include or exclude a random print statement?
Any help would be greatly appreciated because I can't understand how C is pulling numbers out of thin air like this.
Your malloc size is not correct and causes undefined behavior.
The actual memory size is the length of array * size of array type.
The printf in main is actually printing something random in the memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int *myF(int a[],int s, int n);
int *myFunc(int x[],int size,int nnum) {
int i;
size += 1;
//int *y = malloc(size * sizeof(int) );
int *y = malloc(size );
for(i=0;i<size;i++) {
if(i==0)
*y = nnum;
else {
*(y+i) = x[i-1];
printf(" %d",*(y+i)); // <-- ***THIS THING RIGHT HERE***
}
}
return y;
}
int main (int argc, char *argv[]) {
int i;
int x[7] = {1,2,3,4,5,6,7};
int *P = myFunc(x,7,12);
for(i=0;i<8;i++) {
if(i==0) printf("\n");
printf(" %d",*(P+i));
}
free(P);
return 0;
}
If you're interesting in why printf changed the behavior, this post has in-depth explanation.
Also don't forget to free P in the end.

Passing a 2d array with pointers and accessing it gives segmentation fault

im trying to pass a 2D array from main to a function and trying to print it letter by letter
but it keeps giving me segmentation fault
note: the question im trying to solve as mentioned a function with parameter { ArrPrintMatrix(char *(p)[7]) }
so help me by keeping the above thing in mind
#include<stdio.h>
ArrPrintMatrix(char **p,int n) {
int i,j;
for(i=0;i<n;i++) {
for(j=0;j<10;j++) {
printf("%c ",p[i][j]);
}
}
}
main() {
int i;
char c[2][10];
puts("enter two strings");
for(i=0;i<2;i++)
scanf("%s",c[i]);
ArrPrintMatrix((char **) c,2);
}
You should use char p[2][10] not char** p
The following code could work:
#include <stdio.h>
void ArrPrintMatrix(char p[2][10], int n) {
int i;
for (i = 0; i < n; ++i)
printf("%s\n",p[i]);
}
int main() {
int i;
char c[2][10];
puts("enter two strings");
for(i=0;i<2;i++)
scanf("%s",c[i]);
ArrPrintMatrix(c,2);
return 0;
}
you need to change the type of the p var in the print function, and you should also set the array to zero so if the strings that are printing are less than 10 chars with terminator- garbage values are not displayed.
void ArrPrintMatrix(char p[][10],int n) {
int i,j;
for(i=0;i<n;i++) {
for(j=0;j<10;j++) {
printf("%c ",p[i][j]);
}
}
}
int main() {
int i;
char c[2][10]= {0};
puts("enter two strings");
for(i=0;i<2;i++)
scanf("%s",c[i]);
ArrPrintMatrix( c,2);
return 0;
}

Pointer to Pointer array & Stack Smashing error

I need to allocate an array with a malloc and I have to read some numbers from input. This is my code:
#include <stdio.h>
#include <stdlib.h>
void read(int **array, int *array_size)
{
int *tmp;
int i;
scanf("%d", array_size);
*array=malloc(*array_size*sizeof(int));
tmp=malloc(*array_size*sizeof(int));
for(i=0;i<*array_size;i++)
{
scanf("%d", &tmp[i]);
array[i]=&tmp[i];
}
}
//DO NOT EDIT main()
int main()
{
int *array;
int array_size,i;
read(&array,&array_size);
printf("Print array:\n");
for(i=0;i<array_size;i++)
printf("%d\n", array[i]);
return 0;
}
It kinda works, but after displaying values it shows a stack smashing detected (I compiled it with GCC).
I thought the problem is that *array=malloc(*array_size*sizeof(int)), but I can't figure out how to fix it. Is there another way to allocate this array without editing main()? Thank you.
The problem is that you're indexing the wrong array. You should be writing (*array)[i], not array[i]:
void read(int **array, int *array_size)
{
int *tmp;
int i;
scanf("%d", array_size);
*array=malloc(*array_size*sizeof(int));
tmp=malloc(*array_size*sizeof(int));
for(i=0;i<*array_size;i++)
{
scanf("%d", &tmp[i]);
(*array)[i]=tmp[i];
}
}
Of course all this is very complicated - you don't need to actually have that tmp, nor do you need to malloc it. Instead you could very well do something like
void read(int **array, int *array_size) {
int i, *pos;
scanf("%d", array_size);
*array = pos = malloc(*array_size * sizeof(int));
for (i = 0; i < *array_size; i ++, pos ++) {
scanf("%d", pos);
}
}
That is we have the pointer pos to point to the current position in the array where we want to scanf the next integer. On each loop we increment the position.
Naturally, you'd want to check the return values of these scanfs and malloc; and perhaps read should have a different prototype, such as
int *read(int *array_size);
so it could return the pointer to the array directly, or NULL on error.

Resources