I am working on a problem in which i have to print out the reverse of the user-given words from the cmd. I also have to increase the allocated memory in case the number of inputs are greater than the originally given memory. Memory allocation and reallocation appear to be working fine. For some reason, my matrix only stores the last given input in all of its memory.
What is the problem? I even tried printing out the matrix cell values, but they are all filled with the last input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** create_matrix(int cap);
char** matrix_reallocation(char** matrix, int* cap);
void free_matrix(char** matrix, int cap);
void print_reverse_matrix(char** matrix, int words);
int main(){
int cap = 8;
char** matrix = create_matrix(cap);
char tmp_word[1025];
int words = 0;
while (fscanf(stdin,"%s",tmp_word) != EOF){
matrix[words] = tmp_word;
words++;
printf("Words stored: %d, Capacity: %d\n", words, cap);
if (words == cap){
printf("Limit reached, reallocating....\n");
matrix = matrix_reallocation(matrix, &cap);
}
}
//printf("%s", matrix[0]);
//printf("%s", matrix[1]);
//printf("%s", matrix[2]);
//printf("%s", matrix[3]);
print_reverse_matrix(matrix,words);
free_matrix(matrix,cap);
return 0;
}
char** create_matrix(int cap){
char** matrix = malloc(sizeof(char*) * cap);
for (int i = 0; i < cap; ++i)
{
matrix[i] = malloc(sizeof(char*) * 1025);
if (matrix[i] == NULL){
printf("Memory allocation failed\n");
exit(1);
}
}
return matrix;
}
char** matrix_reallocation(char** matrix, int *cap){
char** new_matrix = realloc(matrix, sizeof(char*) * *cap * 2);
printf("1D reallocated\n");
*cap *= 2;
printf("Capacity increased\n");
for (int i = (*cap/2); i < *cap; ++i)
{
new_matrix[i] = malloc(sizeof(char*) * 1025);
if (new_matrix[i] == NULL){
printf("Memory allocation failed\n");
exit(1);
}
}
printf("Succesful reallocation, new capacity: %d\n", *cap);
return new_matrix;
}
void print_reverse_matrix(char** matrix, int words){
for (int i = (words - 1); i >= 0 ; i--)
{
printf("%d ", i+1);
for (int j = (strlen(matrix[i]) - 1); j >= 0 ; j--)
{
printf("%c ", matrix[i][j]);
}
printf("\n");
}
}
void free_matrix(char** matrix, int cap){
for (int i = 0; i < cap; ++i)
{
free(matrix[i]);
}
free(matrix);
}
In each iteration of the loop you overwrite tmp_word and then assign a row in the matrix to it, making them all point to the same string. Instead, you should copy it to the matrix:
char tmp_word[1025];
int words = 0;
while (fscanf(stdin,"%s",tmp_word) != EOF){
strcpy(matric[words], tmp_word); /* Here! */
words++;
printf("Words stored: %d, Capacity: %d\n", words, cap);
if (words == cap){
printf("Limit reached, reallocating....\n");
matrix = matrix_reallocation(matrix, &cap);
}
}
Related
Hello, my question is: How to print out string 1 and string 2, not only string 2. I am new to dynamically memory allocated. My sample code is below, thanks for your help.
Result expected:
Hello
My name is Ken
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
int n, i;
char *ptr;
printf("How many strings you want to display?: ");
scanf("%d", &n);
ptr = (char*)malloc(n * sizeof(n));
if(ptr == NULL){
printf("Failed to allocate the memory to string!\n");
exit(0);
}
for(i = 0; i < n; i++){
printf("String %d: ", i + 1);
fflush(stdin);
scanf("%[^\n]", ptr);
}
printf("\n");
printf("Strings you entered:\n");
for(i = 0; i < n; i++){
printf("%s\n", ptr);
}
}
Please check the below code. I have marked modified lines with a comment starting with // CHANGE.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// CHANGE - free memory when not needed
void free_memory(char** ptr, int n)
{
if (ptr)
{
int i;
for (i = 0; i < n; i++)
{
if (ptr[i])
{
free(ptr[i]);
}
}
free(ptr);
}
}
int main(){
int n, i;
char **ptr; // CHANGE - make a double pointer - array of strings (imagine rows and columns)
printf("How many strings you want to display?: ");
scanf("%d", &n);
ptr = (char**) malloc(n * sizeof(char*)); // CHANGE - allocate memory based on no. of rows (columns are string characters)
if (ptr == NULL) {
printf("Failed to allocate the memory to string!\n");
exit(1);
}
getchar(); // CHANGE - read the newline character else fgets doesn't work
for (i = 0; i < n; i++) {
ptr[i] = (char*) malloc(256 * sizeof(char)); // CHANGE - allocate memory for each row
printf("String %d: ", i + 1);
if ( fgets(ptr[i], 256 * sizeof(char), stdin) == NULL ) {
printf("Failed to get line input\n");
free_memory(ptr, n);
exit(1);
}
ptr[i][strlen(ptr[i]) - 1] = '\0'; // CHANGE - remove extra newline character at the end
}
printf("\n");
printf("Strings you entered:\n");
for (i = 0; i < n; i++) {
printf("%s\n", ptr[i]); // CHANGE - print each row
}
free_memory(ptr, n);
return 0;
}
First, there are two numbers that should be decided:
the number of strings the user wants to input and
the length of the strings (or the lengths of each string).
Each string will be stored in a char*. And all strings together will be stored in a char**. The length of char** will be your n in this case.
And length of each char* can be decided however you want.
I prefer to use a directive #define to define a constant like 100.
You can also do a global or local variable or just a digit.
Also don't forget to free anything you allocate. Check below for details.
And happy coding!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 100
int main(){
int n, i;
// stores all the strings
char **ptr;
printf("How many strings you want to display?: ");
scanf("%d", &n);
// allocate memory of size (n * size of char*)
ptr = (char**)malloc(n * sizeof(char*));
if(ptr == NULL){
printf("Failed to allocate the memory to string!\n");
// for portability to use EXIT_FAILURE,
// which is defined in the standard library
exit(EXIT_FAILURE);
}
// for each pointer, allocate memory of size (MAX_STRING_SIZE * size of char)
for(i = 0; i < n; i++)
// I should put a validity check here but I'm too lazy...
ptr[i] = (char*)malloc(MAX_STRING_SIZE * sizeof(char));
for(i = 0; i < n; i++){
printf("String %d: ", i + 1);
fflush(stdin);
scanf("%[^\n]", ptr[i]); // use ptr[i]
}
printf("\n");
printf("Strings you entered:\n");
for(i = 0; i < n; i++){
printf("%s\n", ptr[i]); // use ptr[i]
}
// free all of them
for(i = 0; i < n; i++)
free(ptr[i]);
free(ptr);
return 0;
}
I am new to C and I was trying to code up a dynamic int array that lets the user type in numbers via terminal untill the user types in -1. So the user can type any amount of int's and the data is reallocated each time another valid int is input.
Sometimes it works as expected other times I get: free(): double free detected in tcache 2
Aborted (core dumped) error.
I am printing the values after every input and everything seems fine untill -1 is input. And the bug only occures every other time.
Here is my Code:
void output(int *ptr, int len){
printf("\n");
for(int i=0; i<len; i++){
printf("%d %p \n", ptr[i], ptr+i);
}
printf("\n");
}
int input(int *ptr, int *size){
int x;
printf("Insert your numbers:\n");
while(1){
scanf("%d", &x);
if(x == -1) break;
size[0]++;
// printf("Size: %d\n", size[0]);
ptr = realloc(ptr, size[0] * sizeof(int));
if(ptr == NULL) return -1;
int indexToStore = size[0]-1;
// printf("Index: %d\n", indexToStore);
ptr[indexToStore] = x;
output(ptr, size[0]);
}
return 0;
}
int main()
{
int size = 0;
int *array = (int*)malloc(sizeof(int));
if(array == NULL) return -1;
input(array, &size);
output(array, size);
input(array, &size);
output(array, size);
free(array); array = NULL;
return 0;
}
The argument ptr of the function input is a copy of what is passed and modifying that will not affect what is passed in caller.
Therefore, the change in buffer via realloc() is not saved from the 1st call of input() to the 2nd call of input() and it will lead to troubles.
You should pass a pointer to what should be modified to have functions modify caller's local things.
#include <stdio.h>
#include <stdlib.h>
void output(int *ptr, int len){
printf("\n");
for(int i=0; i<len; i++){
printf("%d %p \n", ptr[i], ptr+i);
}
printf("\n");
}
int input(int **ptr, int *size){
int x;
printf("Insert your numbers:\n");
while(1){
scanf("%d", &x);
if(x == -1) break;
size[0]++;
// printf("Size: %d\n", size[0]);
*ptr = realloc(*ptr, size[0] * sizeof(int));
if(*ptr == NULL) return -1;
int indexToStore = size[0]-1;
// printf("Index: %d\n", indexToStore);
(*ptr)[indexToStore] = x;
output(*ptr, size[0]);
}
return 0;
}
int main()
{
int size = 0;
int *array = (int*)malloc(sizeof(int));
if(array == NULL) return -1;
input(&array, &size);
output(array, size);
input(&array, &size);
output(array, size);
free(array); array = NULL;
return 0;
}
Hello i am trying to find the frequncey of words in tow dimensional arry but im having problem with my codes so far this is what i have done i tried to find whats wrong using debugger but i cant find anything usefull im new to coding so i would be really happy if someone can tell me the problem
I pointed out where im having problem in my code
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void freeFunction(char** arry, int size);
void insertArry(char** words, int countWords);
void wordFrequency(char** words, int countWords);
int main()
{
char** words=NULL;
int count = NULL;
insertArry(words, &count);
wordFrequency(words,count);
}
void insertArry(char** words, int* countWords)
{
char buffer[11];
int numberC;
printf("How many words?: ");
scanf("%d", &numberC);
getchar();
words = (char**)malloc(numberC * sizeof(char*));
if (words == NULL)
{
printf("No memory");
exit(1);
}
for (int i = 0; i < numberC; i++)
{
printf("Enter word: ");
gets_s(buffer, 11);
words[i] = (char*)malloc(strlen(buffer) + 1);
if (words == NULL)
{
freeFunction(words, i);
exit(1);
}
strcpy(words[i], buffer);
}
*countWords = numberC;
}
void freeFunction(char** arry, int size){
printf("No memory");
for (int j = 0; j < size; j++)
{
free(arry[j]);
}
free(arry);
}
void wordFrequency(char** words, int countWords)
{
int counter = 0;
for (int i = 0; i < countWords; i++) {
for (int j = i + 1; j < countWords; j++)
{
if(strcmp(words[i],words[j])==0) /// ***THIS IS WHERE MY PROBLEM RELAY ITS GIVING ME WEIRD ADDRESSES***
counter += 1;
}
printf("%s:%d",words[i], counter);
counter = 0;
}
}
This is my beginner program experimentation with what I have learned on dynamic memory allocation, pointers, and files. Every time I compile I keep having a segmentation fault. I haven't been able to fix this error that occurs during fscanf().
#include <stdio.h>
#include <stdlib.h>
// create int aboveavg();
double average(int *ptr, int size){
int count = 0;
double sum = 0;
while(count <= size){
sum += *ptr;
ptr++;
count++;
}
sum /= size;
return sum;
}
int main(){
int n = 10;
int *ptr = (int*)calloc(n, sizeof(int)); //allocate dynamic memory
printf("Allocated %d integers\n", n);
FILE *input = fopen("a.txt" , "r"); //open file
if(input = NULL){ //error check
printf("Error! memory not allocated.");
exit(0);
}
int count = 0, i=0;
printf("check point\n");
while(fscanf(input, "%d", &ptr[i]) == 1){ //**Segmentation Fault**
if(count == n){
n *=2;
ptr = (int*)realloc(ptr,n* sizeof(int));
printf("Reallocated to %d integers\n", n);
}
i++;
count++;
}
fclose(input);
double avg = average(ptr, n);
printf("average of %f\n", avg);
free(ptr);
printf("Dynamic array freed\n");
return 0;
}
Searching for an answer (google or stack overflow), hasn't really helped me. Can anyone can hint/point to what I did wrong.
I'm new to this fantastic site and I found it very useful in many occasions, but now I'm dealing with a problem which I can't seem to solve.
I'm a beginner C student and I'm studying dynamic memory allocation.
I want to create a dynamic array of, let's say, integers, allocating memory for it inside a procedure, not in the main function.
This works:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *numbers; // pointer to create a dynamic array
int *test; // pointer to test realloc function
int c;
size_t i = 0;
unsigned int dim; // array's length
// allocate memory for the 1st number
numbers = malloc(sizeof(*numbers));
if (numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]);
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
dim = --i;
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
}
getchar();
return 0;
}
But I want to do this (which doesn't work):
#include <stdio.h>
#include <stdlib.h>
void get_numbers(int **numbers, unsigned int *dim);
int main()
{
int *numbers; // pointer to create a dynamic array
size_t i = 0;
unsigned int dim; // array's length
get_numbers(&numbers, &dim);
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
getchar();
return 0;
}
void get_numbers(int **numbers, unsigned int *dim)
{
int *test; // pointer to test realloc function
int c;
size_t i = 0;
// allocate memory for the 1st number
*numbers = malloc(sizeof(*numbers));
if (*numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]); // Maybe the error is here
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(*numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
*numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
*dim = --i;
}
}
Do I need to use a pointer to a pointer to int, right?
I know I made some mistakes but I can't figure out how to fix them.
Thanks in advance for your replies!
Bye,
Fabio Nardelli
In the first block of code, numbers is of type int*.
In the second block of code, numbers is of type int**.
You have not fixed all the places that need to be fixed because of that change.
My suggestion:
Change the input argument to numbersPtr.
Create a local variable int* numbers.
Before you return from the function, set *numbersPtr to number.
void get_numbers(int **numbersPtr, unsigned int *dim)
{
int* numbers;
...
*numbersPtr = numbers;
}
It will be better to change get_numbers to return numbers.
int* get_numbers(unsigned int *dim)
{
int* numbers;
...
return numbers;
}
and change its usage as:
numbers = get_numbers(&dim);