This is the code:
I do know what is the problem, I tried for hours to fix it, but was not successful
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void input(char ***array1,int * sizeWords,int size)
{
for (int i = 0; i < size; i++)
{
char word[81] = "";
char descrip[201] = "";
int numAgdarot = 0;
//how mach agdarot
printf("how mach of agdarrot you want? ");
scanf("%d", &numAgdarot);
//save the count of agdarot
sizeWords[i] = numAgdarot;
do
{
printf("enter word number %d: ", i);
_flushall();
gets(word);
} while (textSpace(word) == False);
(array1)[i] = (char**)malloc(numAgdarot + 1 * sizeof(char*)); //set the num and agdarot
//save the word
(array1)[i][0] = (char*)malloc(strlen(word) * sizeof(char));
strcpy(array1[i][0], word);
//save the agdarot
for (int j = 1; j <= numAgdarot; j++)
{
printf("enter descrip number %d: ", i);
_flushall();
gets(descrip);
(array1)[i][j] = (char*)malloc(strlen(descrip) * sizeof(char));
strcpy(array1[i][j], descrip);
}
}
}
int main() {
int *sizeWords = NULL;
int size = 0;
char *x=NULL;// = "jk";
char *** array1 = NULL;
printf("enter number of word: ");
scanf("%d", &size);
array1 = (char***)malloc(size * sizeof(char**));
sizeWords = (int*)malloc(size * sizeof(int));
//x = temp(x,sizeWords);
//input the word and agdarot
input(array1, sizeWords, size);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1);
}
return 0;
}
I get a "HEAP CORRUPTION DELETED" error after Normal block. Why?
If i used a debugger I see the char * but i can not do a free..
Doing
malloc(strlen(word) * sizeof(char));
is almost always wrong. Remember that strings also contains an extra character that is not reported by the strlen function, the terminator character '\0'. That means your next call to strcpy will write beyond the end of the allocated memory.
What you should do is allocate memory for that extra terminator character as well:
array1[i][0] = malloc(strlen(word) + 1);
[Note that I changed the code, first because the parentheses around array are not needed, secondly because you in C one should not cast the return of malloc, and third because sizeof(char) is specified to always be 1.]
Remember to change on all other places where you use strlen in a call to malloc.
These allocations are too small:
(array1)[i][0] = (char*)malloc(strlen(word) * sizeof(char));
strcpy(array1[i][0], word);
// ...
(array1)[i][j] = (char*)malloc(strlen(descrip) * sizeof(char));
strcpy(array1[i][j], descrip);
You need an extra character for the terminating \0. strcpy() is writing into unallocated space.
Save yourself some trouble and:
(array1)[i][0] = strdup(word);
// ...
(array1)[i][j] = strdup(descrip);
And, as pointed out in the comments,
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1);
}
should become:
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1[i]);
}
free(array1);
Related
This code scans number then he create array with malloc, then i scan strings, i put then inside the array with another malloc, then i sort the strings and print them. I build this code with mallocs and i put array inside array,i have leaks in this code, where i need to put free() function and how i put free()? I tried many times to solve this leaks but its not working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sort(char** names, int length);
void print_array(char** names, int length);
int main()
{
int num_of_friends = 0;
int i = 0;
char name[50] = { 0 };
char** names = NULL;
printf("Enter number of friends: ");
scanf("%d", &num_of_friends);
getchar();
names = malloc(sizeof(char) * num_of_friends);
for ( i = 0; i < num_of_friends; i++)
{
printf("Enter name of friend %d: ", i + 1);
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = 0;
names[i] = malloc(sizeof(char) * strlen(name));
strcpy(names[i], name);
}
sort(names, num_of_friends);
print_array(names, num_of_friends);
getchar();
return 0;
}
void sort(char** names, int length)
{
char temp[50] = { 0 };
int i = 0;
int j_min = 0;
int j = 0;
for ( i = 0; i < length - 1; i++)
{
j_min = i;
for ( j = i+1; j < length; j++)
{
if (strcmp(names[j], names[j_min]) < 0)
{
j_min = j;
}
}
if (j_min != i)
{
strcpy(temp, names[i]);
strcpy(names[i], names[j_min]);
strcpy(names[j_min], temp);
}
}
}
void print_array(char** names, int length)
{
int i = 0;
for (i = 0; i < length; i++)
{
printf("Friend %d: %s \n", i + 1, names[i]);
}
}
For names, you are allocating sizeof (char) times the user provided number of bytes. This is needs to be sizeof (char *), giving you enough room for each pointer value.
names = malloc(sizeof (char *) * num_of_friends);
You need to allocate one additional byte for the null terminating character ('\0'). sizeof (char) is guaranteed to be 1, making that statement redundant.
names[i] = malloc(strlen(name) + 1);
Before the end of main, you need to free each element of names, and then names itself.
sort(names, num_of_friends);
print_array(names, num_of_friends);
getchar();
for (i = 0; i < num_of_friends; i++)
free(names[i]);
free(names);
return 0;
Your sort function may attempt to copy strings between buffers of differing size. You need to swap pointers instead.
Example:
void swap(char **a, char **b) {
char *c = *a;
*a = *b;
*b = c;
}
void sort(char **names, size_t length) {
for (size_t i = 0; i < length - 1; i++)
for (size_t j = i + 1; j < length; j++)
if (strcmp(names[i], names[j]) > 0)
swap(names + i, names + j);
}
The program reads a file which includes one word in every line.After reading random word put random word in a pointer and return the pointer .in main function
printf("%s",func("example.txt",str)) it prints different string when the program run.I want to do this in 2d array(20*20) like table,but i could not imagine how to do this.When i print the the function in internal loop,it give me the same word in every loop step.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char *word(char *file, char *str);
int main() {
char *str ;
int i, j;
str = (char *)malloc(20);
srand(time(NULL));
char *puzzle[20][20];
for (i = 0; i < 20; i++) {
for (j = 0; j < 20; j++) {
puzzle[i][j] = word("words.txt", str);
}
}
for (i = 0; i < 20; i++) {
for (j = 0; j < 20; j++) {
printf("%s ", puzzle[i][j]);
}
printf("\n");
}
}
char *word(char *file, char *str) {
int end, loop, line;
FILE *fd = fopen(file, "r");
if (fd == NULL) {
printf("Failed to open file\n");
return (NULL);
}
srand(time(NULL));
line = rand() % 100 + 1;
for (end = loop = 0; loop < line; ++loop) {
if (0 == fgets(str, 20, fd)) {
end = 1;
break;
}
}
if (!end)
return (char *)str;
fclose(fd);
free(str);
}
I do not have your words.txt file, so I've created some random strings below.
And a note:
Because your nested loop is in the main, your code opens the file in the sub function and returns w/o closing it; then returns to the sub and reopens, and again, and again... It's always better to read at once and close the file before returning from the sub.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char **word(int countString, int maxChars) {
int i;
int j;
int k;
// allocate memory for pointers that are pointing to each string
char **arrStr = malloc(countString * sizeof(char *));
// srand(time(NULL));
for (i = 0; i < countString; i++) {
// create a random string with a length of 'k'
// say, 5 <= k <= maxChars
// that (+ 1) is for the string terminating character '\0'
k = (rand() % (maxChars - 5)) + 5 + 1;
// allocate memory for string
arrStr[i] = malloc(k * sizeof(char));
for (j = 0; j < k - 1; j++) {
*(arrStr[i] + j) = rand() % 26 + 'A';
}
*(arrStr[i] + j) = '\0';
}
return arrStr;
}
int main() {
int countString = 10;
int maxChars = 20;
char **arrStr = NULL;
int i;
arrStr = word(countString, maxChars);
for (i = 0; i < 10; i++) {
printf("%s\n", *(arrStr + i));
}
// do not forget to free the strings
// and then the string pointers (array)
return 0;
}
How will I be able to maintain the position of the allocated memory so that freeing memory of a sorted array will not be affected?
I am trying to sort the pointer array. I noticed that when I free the words double pointer variable it will give an error HEAP CORRUPTION DETECTED. The input I entered was "f ff 1".
Unsorted: f ff 1
Sorted: 1 f ff
I noticed that when I sort and free it will expect the same order which is "f ff 1". That is why I got some error.
Any suggestion on how will be able to free the sorted pointer array?
#include <stdio.h>
/*
A logical type
*/
typedef enum {
false,
true,
} bool;
/*
Bubble Sort
*/
void sort(char *myargv[], int n)
{
int i, j, cmp;
char tmp[256];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(myargv[j], myargv[j+1]);
if (cmp > 0)
{
strcpy(tmp, myargv[j+1]);
strcpy(myargv[j+1], myargv[j]);
strcpy(myargv[j], tmp);
}
}
}
}
void printArray(char *myargv[], int myargc)
{
int i = 0;
for (i = 0; i < myargc; ++i) {
printf("myargc[%d]: %s\n",i , myargv[i]);
}
}
int main (int argc, char *argv[])
{
char text[256];
char *myargv[256];
char *myargvTemp[256];
int myargc;
int i = 0;
int text_len;
bool new_word = false;
int index_start_word = 0;
char **words; //this will store the found word
int count = 0;
while(1){
printf( "Enter text:\n");
gets(text); //get the input
text_len = strlen(text); //get the length of the text
words = (char **) malloc(text_len * sizeof(char));
if (strlen(text) == 0 || text == '\0') exit(0); //exit if text is empty
for (i = 0; i < text_len ; ++i){
if(text[i] != ' '){ //if not space
if(new_word == false){
new_word = true;
index_start_word = i;
}
} else {
if (new_word == true) {
words[count] = (char *)malloc(i - index_start_word * sizeof(char)+1); //memory allocation
strncpy(words[count], text + index_start_word, i - index_start_word);
words[count][i - index_start_word] = '\0'; //place NULL after the word so no garbage
myargv[count] = words[count];
new_word = false;
count++;
}
}
if (new_word == true && i == text_len-1){
words[count] = (char *)malloc(i - index_start_word * sizeof(char)+2);
strncpy(words[count], text + index_start_word, (i+1) - index_start_word);
words[count][(i+1) - index_start_word] = '\0';
myargv[count] = words[count];
new_word = false;
count++;
}
}
myargc = count;
//not sorted
printf("myargc is: %d\n", myargc);
printArray(myargv, myargc);
//sorting happen
sort(&myargv, myargc);
printf("-----sorted-----\n");
printf("myargc is: %d\n", myargc);
printArray(myargv, myargc);
memset(myargv, 0, 255);
count = 0;
i = 0;
//free the memory of words
for (i=0; i<myargc; ++i) {
free(words[i]);
}
}
return 0;
}
There are at least 2 problems in your code:
you do not allocate enough space for the array of pointers: change the words = (char **) malloc(text_len * sizeof(char)); to this:
words = malloc(text_len * sizeof(char *));
This allocation is actually incorrect: you should compute the number of words and allocate the correct size for the pointer array, or use a fixed size array.
you swap the contents of the strings instead of swapping the pointers. This is incorrect as the various strings do not have the same lengths.
Here is a corrected version of the sorting function:
void sort(char *myargv[], int n) {
int i, j, cmp;
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++) {
for (j = 0; j < n-1; j++) {
cmp = strcmp(myargv[j], myargv[j+1]);
if (cmp > 0) {
char *tmp = myargv[j+1];
myargv[j+1] = myargv[j];
myargv[j] = tmp;
}
}
}
}
You want words to hold pointers to char so you need to change
words = (char **) malloc(text_len * sizeof(char)); //will allocate array of single byte
to
words = (char **) malloc(text_len * sizeof(char *));// will allocate array of pointers
So basically what my program did before i had to change it so that it would accept arbitrary values, was to take x-amount of words and the size of the words would also be arbitrary. (both are user inputted). I did this via a multiArray.
Then sorted according to alphabetical-order.
I'm just going to put it out there as my code is shit and I'm very unfamiliar with the usage of arbitrary-strings and pointers. I've read up on it in the manual but the concept needs to sink in a little bit first i believe. Anyhow, I get the error: "Abort trap: 6" when i run the program. Could anyone please help me fix this problem so that i can see how the code would look like if it was actually working, i think that would help me understand both pointers and allocating memory a lot better. Forever in debt if you do.
Current code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LENGTH 10
int main(){ //8
char *name;
char tname[] = {0};
char temp[] = {0};
int i=0, j=0, n=0;
ssize_t bytes_read;
size_t bytes_number;
printf("Enter the amount of words you want to input: ");
scanf("%d", &n);
printf("Enter %d words: ",n);
bytes_number = MAX_LENGTH;
name = (char *) malloc (bytes_number+ 1);
bytes_number = 0;
bytes_read = getline(&name, &bytes_number, stdin);
if (bytes_read == -1){
puts("ERROR!");
free(name);
}
for (i = 0; i < n; i++){
strcpy(&tname[i], &name[i]);
}
for (i = 0; i < n - 1 ; i++){
for ( j = i + 1; j < n; j++){
if (strcmp(&name[i], &name[j]) > 0){
strcpy(temp, &name[i]);
strcpy(&name[i], &name[j]);
strcpy(&name[j], temp);
}
}
}
printf("\n------------------------------------------\n");
printf("%-3s %4s %11s\n", "Input","|", "Output");
printf("------------------------------------------\n");
for (i = 0; i < n; i++)
{
printf("%s\t\t%s\n", &tname[i], &name[i]);
}
printf("------------------------------------------\n");
}
This
strcpy(&tname[i], &name[i]);
is completely wrong, if you just want to copy all the characters, then it's just
strcpy(tname, name);
which is equivalent to
for (size_t i = 0 ; name[i] != '\0' ; ++i)
tname[i] = name[i];
using strcpy(&tname[i], &name[i]) is wrong because it will copy all the bytes from name until '\0' is found, at every loop starting at the i-th character.
But this will fail again because tname is does not have room, it's an array with just one element.
Since you want to sort the strings, you DO NOT NEED TO COPY them. Just swap the pointers. Also
char temp[] = {0};
only allocates 1 character, thus
strcpy(temp, name);
will invoke Undefined Behavior.
Try this, maybe it's what you need
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int
main(void)
{
char **words;
char *temp;
int word_count;
int actual_count;
char *word;
size_t length;
int result;
printf("Enter the amount of words you want to input: ");
if (scanf("%d%*c", &word_count) != 1)
return -1; // Input error
printf("Enter '%d' words:\n", word_count);
words = NULL;
word = NULL;
result = -1;
actual_count = 0;
length = 0;
for (int i = 0 ; i < word_count ; ++i)
{
char **pointer;
printf("Word(%d) > ", i + 1);
if ((length = getline(&word, &length, stdin)) <= 0)
goto cleanup;
// Grow the array of words
pointer = realloc(words, (i + 1) * sizeof(*pointer));
if (pointer == NULL)
goto cleanup; // Memory Exhausted
// Now it's safe to overwrite `words'
words = pointer;
words[i] = malloc(length);
if (words[i] == NULL)
goto cleanup; // Memory Exhausted
memcpy(words[i], word, length);
words[i][length - 1] = '\0'; // Replace '\n' with '\0'
actual_count += 1;
}
printf("Input : ");
for (int i = 0 ; i < actual_count ; ++i)
printf("%s\t", words[i]);
printf("\n");
for (int i = 0; i < actual_count - 1 ; i++)
{
for (int j = i + 1 ; j < actual_count ; ++j)
{
if (strcmp(words[i], words[j]) <= 0)
continue;
temp = words[i];
words[i] = words[j];
words[j] = temp;
}
}
printf("Output: ");
for (int i = 0 ; i < actual_count ; ++i)
printf("%s\t", words[i]);
printf("\n");
result = 0;
cleanup:
free(word);
for (int i = 0; i < actual_count ; i++)
free(words[i]);
free(words);
return result;
}
Note: This would consider an empty word (made completely of white space characters), as a valid word.
I'm using a dynamic array of strings in C:
char** strings;
I initialize it:
int max = 10;
strings = malloc(sizeof(char*) * max);
And copy a couple of dummy strings:
char* str = "dummy";
for (int i = 0; i < max; i++) {
strings[i] = malloc(strlen(str) + 1);
strncpy(strings[i], str, strlen(str) + 1);
}
Yet when I try to print this:
for (int i = 0; i < max; i++)
printf("array = %s", strings[i])
I get this error from Splint:
Value strings[] used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
Checking for NULL like this will not help:
for (int i = 0; i < max; i++)
if (strings[i] != NULL)
printf("array = %s", strings[i])
since strings[i] is still used "before definition".
Any ideas on how to solve this?
Edit: Will try this with a linked list instead, I think.
Also, complete code listing:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char** strings;
int i;
int max = 10;
char* str = "hello";
// Dynamic array with size max
strings = malloc(sizeof(char*) * max);
// Abort if NULL
if (strings == NULL)
return (-1);
// Define strings
for (i = 0; i < max; i++)
{
strings[i] = malloc(strlen(str) + 1);
// Abort if NULL
if (strings[i] == NULL)
{
// Undetected memory leak here!
free(strings);
return (-1);
}
strncpy(strings[i], str, strlen(str) + 1);
}
// Print strings
for (i = 0; i < max; i++)
{
if (strings[i] != NULL)
printf("string[%d] = %s\n", i, strings[i]);
}
// Free strings
for (i = 0; i < max; i++)
{
if (strings[i] != NULL)
free(strings[i]);
}
free(strings);
return 0;
}
I do not have Splint on my machine, so i cannot test with it, just an another way to your task:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int i, len, max;
char* str = "hello";
len = strlen(str) + 1;
max = 10;
char strings[max][len];
for (i = 0; i < max; i++) {
strcpy(strings[i], str);
}
for (i = 0; i < max; i++) {
printf("string[%d] = %s\n", i, strings[i]);
}
return 0;
}
Avoid creating non-continuous memory it would be better approach if you allocate memory in single malloc call.
Memory can be freed in single free call instead of multiple free call
max_rows * sizeof(char) will allocate 2 * 1
((strlen(str) * N) + 1) will allocate memory for every N element.
Here is my approch
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
size_t max_rows = 2;
char* str = "dummpy";
char* vec_s = (char *) malloc( max_rows * sizeof(char) * ((strlen(str) * max_rows) + 1));
for (int i = 0; i < max_rows; i++){
strcpy((vec_s + i), str);
printf("vec_s[%d]=%s\n", i, (vec_s + i));
}
free(vec_s);
return 0;
}