Can you please help me with fixing below code. Not sure where the segmentation fault is.
char str[] = "00ab00,00cd00";
char **strptr;
int i;
strptr = malloc(sizeof(char*) * 2);
strcnt = 0;
int j=0;
for(i=0;i<sizeof(str);i++) {
char c = *(str+i);
printf("%c", c);
if(c==',') {
strcnt++;
j=0;
}
strptr[strcnt][j++] = c;
}
Please ignore my poor coding :)
PS: I know its possible to split using strtok() easily.
Not sure where the segmentation fault is
As others have mentioned in the comments, you are not assigning memory to the pointers strptr[0] and strptr[1] but, you are trying to access them. This leads to segmentation fault.
Use a for loop to initially assign memory to strptr[0] and strptr[1]
strptr = malloc(sizeof(char*) * 2);
for(i = 0; i < 2; i++) //here, initialise each to 1 byte
{
strptr[i] = malloc(1);
}
strcnt = 0;
Here's a question on how to initialise a pointer to a pointer.
then, resize them at each step as you add additional character using the realloc() function.
for(i = 0, j = 0; i < sizeof(str); i++)
{
strptr[strcnt] = realloc(strptr[strcnt], j + 2);
//here, you resize each time to provide space for additional character using realloc()
char c = *(str + i);
printf("%c", c);
if(c == ',')
{
++strcnt;
j=0;
continue; //use a continue here
}
strptr[strcnt][j] = c;
strptr[strcnt][++j] = '\0';
//to provide null terminating character at the end of string (updated to next position at every iteration)
}
don't forget to free() the allocated memory
for( i=0; i<2; i++)
{
printf("%s\n", strptr[i]); //just to display the string before `free`ing
free(strptr[i]);
}
free(strptr);
Altogether your code would be something like this:
char str[] = "00ab00,00cd00";
char **strptr;
int i, j;
int strcnt;
strptr = malloc(sizeof(char*) * 2);
for(i = 0; i < 2; i++)
{
strptr[i] = malloc(1);
}
strcnt = 0;
for(i = 0, j = 0; i < sizeof(str); i++)
{
strptr[strcnt] = realloc(strptr[strcnt], j + 2);
char c = *(str + i);
printf("%c", c);
if(c == ',')
{
++strcnt;
j=0;
continue;
}
strptr[strcnt][j] = c;
strptr[strcnt][++j] = '\0';
}
for( i=0; i<2; i++)
{
printf("%s\n", strptr[i]);
free(strptr[i]);
}
free(strptr);
return 0;
Related
I can't seem to figure out what is causing this problem. I am on a virtual machine with Ubuntu and using Geany to code. Everything should be right however, it still pops up, so do I run out of memory or is the buffer overloaded? Does anyone have an idea? Would greatly appreciate any feedback.
Would it be safe to bypass GCC stack smashing detection? Thank you in advance.
#define MAX_STR 40
void ProcessPerson(char entry[]);
int main(void)
{
char data[][MAX_STR] = {"Maria,Kask",
"Johanna-Maria,Kask",
"Kalev Kristjan,Kuusk"};
int i;
int numOfPeople = sizeof(data) / MAX_STR;
printf("Number of people: %d\n\n", numOfPeople);
for (i = 0; i < numOfPeople; i++)
{
ProcessPerson(data[i]);
}
return 0;
}
void ProcessPerson(char entry[])
{
int i, j;
char str[2][4] = {""};
printf("Processing line: '%s'\n", entry);
for (i = 0; i < 40; i++)
{
j = 0;
while (j < 4)
{
str[0][j] = entry[j];
j++;
}
if (entry[i] == ',')
{
break;
}
}
str[0][strlen(str[0]) - 1] = '\0';
j = 0;
i++;
while (j < 4)
{
str[1][j] = entry[i];
i++;
j++;
}
str[1][strlen(str[1]) - 2] = '\0';
str[0][0] = str[0][0] + 32;
str[1][0] = str[1][0] + 32;
for (i = 0; i < 40; i++)
{
if (entry[i] == ',')
{
entry[i] = ' ';
break;
}
}
char email[14] = " ";
strcat(email, str[0]);
strcat(email, str[1]);
strcat(email, "#ttu.ee");
printf("Nimi: %s\n", entry);
printf("E-post:%s\n\n", email);
}
str[1][strlen(str[1]) - 2] = '\0';
You didn't null terminate str[1], hence you can't sensibly call strlen(str[1]). What's more, there's not even room in str for the terminating null character after copying four characters into str[1].
Please, help with the code.
Requirement:
Write a function my_union that takes two strings and returns, without doubles, the characters that appear in either one of the strings.
Example:
Input: "zpadinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output: "zpadintoqefwjy"
My code:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char *my_union(char *a, char *b) {
char *str;
// Algorithm for excluding nonunique characters from string a(given in
// parameters).
str[0] = a[0];
int k = 1;
str[k] = '\0';
for (int i = 1; a[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == a[i]) {
is = false;
break;
}
}
if (is) {
str[k] = a[i];
k++;
str[k] = '\0';
}
} // In this case we are excluding excess character 'n' from "zpadinton", so
// str is equal to "zpadinto".
// Algorithm for adding unique characters from array b(given in parameters)
// into str.
for (int i = 0; b[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == b[i]) {
is = false;
break;
}
}
if (is) {
strncat(str, &b[i], 1);
}
}
return str;
}
The first algorithm is almost identical with second, but it doesn't work(. Mb I messed up with memory, give some advice, pls.
If you mean, get the unique characters from two strings and store them into a new string, try this code ;
First, you must allocate a memory for str. In your code, str is not pointing allocated memory location, so you will probably get segmentation fault.
int contains(const char * str,char c)
{
for (int i = 0; i < strlen(str); ++i)
if(str[i] == c)
return 1;
return 0;
}
char * my_union(char *a, char*b)
{
char * res = (char*)malloc(sizeof(char)*(strlen(a) + strlen(b)));
int pushed = 0;
for (int i = 0; i < strlen(a); ++i)
{
if(!contains(res,a[i])){
res[pushed] = a[i];
pushed++;
}
}
for (int i = 0; i < strlen(b); ++i)
{
if(!contains(res,b[i])){
res[pushed] = b[i];
pushed++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
char string1[9] = "abcdefgh";
char string2[9] = "abegzygj";
char * result = my_union(string1,string2);
printf("%s\n", result);
return 0;
}
Also, do not forget the free the return value of my_union after you done with it.
I have been trying to figure out how to modify an array of char pointers but no matter what I do there appears to be no change below are the three arrays I'm trying to change including the call to the function I'm using.
char*cm1[5];
char*cm2[5];
char*cm3[5];
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
The code below is the function itself.I was thinking that maybe it involves a double pointer but if I try *cmd to change the array I get a segmentation fault.
void setupCommands(char **cmd[], char* commands[],char file[],int index){
char str1[255];
strcpy(str1,commands[index]);
char newString [5][255];
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=str1[i];
j++;
}
}
for(i = 0; i < ctr; i++){
//printf(" test2 %s \n", newString[i]);
cmd[i] = newString[i];
//printf(" test2 %d %s \n", i,cmd[i]);
}
//printf("index %d", i);
cmd[i]= file;
cmd[i + 1] = NULL;
//execvp(cmd[0],cmd);
//cmd
}
There are a few issues with your code:
you are trying to return references to the local 'char newString [5][255]' when the function exits. In simple worlds - never return anything locally allocated on the stack. This is the reason you are getting the segmentation fault.
char **cmd[] must be declared char *cmd[] - even though you will get a warning from the compiler assignment from incompatible pointer type, the code would run and execute correctly(essentially **cmd[] would do the same work as *cmd[], even though it's not of correct type) if you didn't return references to the local object;
Easy and simple optimization is just to remove the array str1 and directly operate on the array commands.
Apart from this simple optimization I have changed your code to overcome the segmentation fault, by allocating on the heap, instead on stack(will live until the program terminates) the multidimensional array, and I also calculate it's size so I will know how much memory to allocate. Now it's safe to return references to it.
Note that more optimizations could be made, but for the sake of the simplicity this is the bare minimal for this code to work.
int setupCommands(char *cmd[], char *commands[], char file[], int index)
{
int j = 0;
int ctr = 0;
int i = 0;
int rows = 0;
int cols = 0;
char **newString = NULL;
while(commands[index][i])
{
if (commands[index][i] == ' ')
{
++rows;
}
++i;
}
++rows;
cols = strlen(commands[index]) + 1;
newString = malloc(rows * sizeof(*newString));
if (newString == NULL)
{
return -1;
}
for (i = 0; i < rows; ++i)
{
newString[i] = malloc(cols * sizeof(*newString));
if (newString[i] == NULL)
{
return -1;
}
}
for(i = 0; i <= strlen(commands[index]); i++){
if(commands[index][i] == ' '|| commands[index][i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=commands[index][i];
j++;
}
}
for(i = 0; i < ctr; i++){
cmd[i] = newString[i];
}
cmd[i]= file;
cmd[i + 1] = NULL;
return 0;
}
First of all - being the three stars pointer programmer is not good :)
You assign it with pointer to the local variable which is not longer available after the function return
But if you still want the three stars pointers:
char **cm1;
char **cm2;
char **cm3;
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
#define MAXWORD 256
int setupCommands(char ***cmd, const char *commands,const char *file,int index){
char str1[255];
strcpy(str1,commands[index]);
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
*cmd = malloc(sizeof(char *));
**cmd = malloc(MAXWORD);
if(!*cmd || !**cmd)
{
/* do spmething if mallocs failed*/
return -1;
}
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
(*cmd)[ctr][j] = '\0';
ctr++;//next row
*cmd = realloc((ctr + 1) * sizeof(int));
(*cmd)[ctr] = malloc(MAXWORD);
if(!*cmd || !*cmd[ctr])
{
/* do spmething if mallocs failed*/
return -1;
}
j=0;// for next word, init index to 0
}else{
(*cmd)[ctr][j]=str1[i];
j++;
}
}
*cmd = realloc(sizeof(char *) * ctr + 2)
(*cmd)[ctr - 2] = malloc(MAX);
if(!*cmd || !*cmd[ctr - 2])
{
/* do spmething if mallocs failed*/
return -1;
}
strcpy((*cmd)[ctr - 2], file);
(*cmd)[ctr - 1] = NULL;
return 0;
//execvp(cmd[0],cmd);
//cmd
}
you can improve many things (for example do not realloc every time but in the larger chunks) and I did not change anything in your code logic.
I'm trying to pass a local array from a function letter_remover, which reads an original array, removes vowels + h, w and y, then copies that into a new array. This new array is then passed to main.
For example input plutonium would become pltnm. However when I call the function in main and print out the new array, it will duplicate some letters, for instance plltnm is printed.
void array_filler (char a[]);
char * letter_remover (char b[]);
int main (void)
{
char name[MAX];
char *p;
int i;
array_filler(name);
p = letter_remover(name);
printf("Local array passed back: ");
for (i = 0; i < MAX; i++)
{
printf("%s", p);
p++;
}
return 0;
}
If I print the new array created in the function letter_remover, it prints correctly. The letter_remover function creates the new array as a static char[] array and returns a char *
array_filler contains:
void array_filler (char a[])
{
printf("Type name: ");
int i = 0, c;
while ((c = getchar()) != '\n')
{
c = tolower(c);
if (isalpha(c))
{
a[i] = c;
i++;
}
}
a[i] = '\0';
printf("Name inside array: %s\n", a);
}
letter_remover contains:
char * letter_remover (char b[])
{
int i;
static char c[MAX];
char a[] = "aeiouywh";
printf("Name without forbidden characters: ");
for (i = 0; b[i] != '\0'; i++)
{
if (!strchr(a, b[i]))
{
c[i] = b[i];
printf("%c", c[i]);
}
}
c[i] = '\0';
printf("\n");
return c;
}
In main, you probably want to say
for (i = 0; i < MAX; i++)
{
printf("%c", p[i]);
p++;
}
In order to print each char in p. Since this will output beyond the 0 char, a better way would be to simply say printf("%s", p);, without a loop. Or just printf(p); if you trust the string! Or puts(p); which would apparently print a newline as well, which is most likely desirable for a terminal.
Your array index, into c, increases every time you go around the loop...instead you only need to change the index to c, when you actually copy a legal character.
for (j = 0, i = 0; b[i] != '\0'; i++)
{
if (!strchr(a, b[i]))
{
c[j] = b[i];
j++;
printf("%c", c[j]);
}
}
c[j] = '\0';
The main problem is here, in letter_remover:
for (i = 0; b[i] != '\0'; i++)
{
if (!strchr(a, b[i]))
{
c[i] = b[i];
printf("%c", c[i]);
}
}
c[i] = '\0';
You're using the same index for b and c. So at the end of the loop c contains NULL bytes at the spots where a letter is removed (because the array is static, it is initialized to all zeros). You need to use a separate index for c when you write to it:
for (i = 0, j = 0; b[i] != '\0'; i++)
{
if (!strchr(a, b[i]))
{
c[j] = b[i];
printf("%c", c[j]);
j++;
}
}
c[j] = '\0';
Then main where you're printing the result:
for (i = 0; i < MAX; i++)
{
printf("%s", p);
p++;
}
You're printing out the complete string repeatedly starting at each character. So the first time through it print "pl" before it hits a NULL bytes, the the next time it starts at the "l" and prints that again before it hits the NULL byte, and so on.
Once you apply the first fix, all you need to do is print it once:
printf("%s", p);
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);