This is my code:
#include <stdio.h>
#include <stdlib.h>
void getinfo(unsigned int a, unsigned int b, char **s);
int main(){
unsigned int len_max = 8;
unsigned int current_size = 0;
char *pStr = malloc(len_max);
if(pStr == NULL){
perror("\nMemory allocation\n");
return EXIT_FAILURE;
}
current_size = len_max;
printf("Inserisci hostname: ");
getinfo(len_max, current_size, &pStr);
printf("\nLa stringa inserita รจ: %s\n", pStr);
free(pStr);
return EXIT_SUCCESS;
}
void getinfo(unsigned int a, unsigned int b, char **pStr){
unsigned int i = 0;
char c = EOF;
while((c = getchar()) != '\n'){
*pStr[i++] = (char)c;
if(i == b){
b = i+a;
if((*pStr = realloc(*pStr, b)) == NULL){
perror("\nMemory allocation error\n");
exit(EXIT_FAILURE);
}
}
}
*pStr[i]='\0';
}
When i execute this code i got a segmentation fault when i press enter (after i've wrote the string).
I'm sure the problem is into the function (probably the problem is the *s pointer) but i don't know how to correct it...
You have a precedence problem. You need to use
(*s)[i++] = ...
instead of
*s[i++] = ...
Similarly you need
(*s)[i]='\0';
When you write *s[i] you are indexing s. But you want to index *s, and hence require the parentheses.
I've not checked the rest of your code, but I hope this helps you on your way to debugging the rest of it, if indeed there are more errors.
The problem is with *s[i++] = (char)c; try turning it into (*s)[i++] = (char)c; with the parenthesis around the *s. As well as (*s)[i] = '\0'.
Related
EDIT: Have included only the relevant code
I have to manipulate an input string that looks like this
create /foo
create /foo/bar
write /foo/bar "text"
create /foo/bar/baz
And I've created this program (you don't need to look at all of it)
and the problem I have is with the function printAllFolders() which is called in the main() and it is defined right under the main() function. The problem must be in that function. Is it correct to pass the string in the struct path[] giving the parameter
comando->path ?
When I put that function in the main it does give me segmentation fault issue. The rest works just fine.
EDIT: just to be clear, the printAllFolders() does print all the strings in the path array, so I just need to pass the path[255] array, not the one with all two indexes.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct _command {
unsigned char command[10];
unsigned char path[255][255];
int pathLevels;
} command;
command* createCommandMul(unsigned char* str);
void printfAllFolders(unsigned char* stringhe, int lengthArray);
int main() {
command* comando = (command*) malloc(sizeof(command));
unsigned char* upPath = NULL;
unsigned char* allPath = NULL;
FILE* fp;
unsigned char* line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/Users/mattiarighetti/Downloads/semplice.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
comando = createCommandMul(line);
upPath = upperPath(comando);
allPath = fullPath(comando);
printfAllFolders(comando->path, comando->pathLevels);
}
fclose(fp);
if (line)
free(line);
return 0;
}
void printfAllFolders(unsigned char* stringhe, int lengthArray) {
unsigned char* stringa = stringhe;
int length = lengthArray;
if (length == 0) printf("Cartella %s", stringa[length]);
for (int i = 0; i < length+1; i++) {
printf("Cartella %d %s\t", i, stringa[i]);
}
}
command* createCommandMul(unsigned char* str) {
unsigned char* c = str;
command* commandPointer = (command*) malloc(sizeof(command));
int commandIndex = 0;
int pathLevel = 0;
int pathIndex = 0;
/* Parte Comando */
while(*c != ' ' && commandIndex<10) {
commandPointer->command[commandIndex] = *c++;
commandIndex++;
}
commandPointer->command[commandIndex] = '\0';
while(*c == ' ') c++;
while(*c == '/') c++;
/* Parte Path*/
while(*c!='\0') {
if (*c == '/') {
commandPointer->path[pathLevel][pathIndex] = '\0';
pathLevel++;
pathIndex = 0;
c++;
} else {
commandPointer->path[pathLevel][pathIndex] = *c++;
pathIndex++;
}
}
commandPointer->path[pathLevel][pathIndex] = '\0';
commandPointer->pathLevels = pathLevel;
return commandPointer;
}
Perhaps there is some confusion about the difference between an array:
path[255][255]
and a pointer
unsigned char* stringhe
When passing the array -as- a pointer:
printfAllFolders(comando->path, ...
the printfAllFolders() function sees stringhe as a memory address where there happens to be an unsigned char stored. The printAllFolders() function does not know that stringhe actually points to a more complex object (array of unsigned char with [255][255] dimensions).
One fix to the question code is to change:
void printfAllFolders(unsigned char* stringhe, int lengthArray)
to the following:
void printfAllFolders(unsigned char stringhe[255][255], int lengthArray)
This passes additional information to the function needed to understand the more complex nature of stringhe.
Of course, the following line (again) removes this needed information:
unsigned char* stringa = stringhe;
Perhaps this line ^above^ should be eliminated?
Then change the line:
if (length == 0) printf("Cartella %s", stringa[length]);
to:
if (length == 0) printf("Cartella %s", stringhe[length]);
and then change line:
printf("Cartella %d %s\t", i, stringa[i]);
to:
printf("Cartella %d %s\t", i, stringhe[i]);
#include <stdio.h>
char *strcat_ (char s1[], char s2[]) {
int x = 0, y = 0;
while (s1[x] != '\0') {
x++;
}
while (s2[y] != 0) {
s1[x] = s2 [y];
x++;
y++;
}
s1[x] = '\0';
return s1;
}
main() {
char c;
c = *strcat_("John ", "Trump");
printf ("%s", &c);
}
So there's my code, and when I try to run I get this "Bus error: 10".
I'm really new at this, so please bare that in mind.
Thanks for the help.
There are some problems in these lines -
char c;
c = *strcat_("John ", "Trump");
printf ("%s", &c);
1. Your function return char * not char .
2. While calling function do not apply * operator to it .
3. You tend to modify a constant in your function which causes UB and as well as not enough memory to hold the concatenated part .
c = *strcat_("John ", "Trump");
^^^^ This is a constant.
4. In printf don't pass address of variable if you want to print the content.
You can write as follows -
char a[100]="John";
//char c;
strcat_(a, "Trump") //let type be void and let char a[] hold complete string
Having trouble figuring out why I run into a segmentation fault with the longer piece of code.
I take this and run it fine.
struct Earthquake
{
char *prevString;
char *magString;
char *postString;
};
int main(void)
{
struct Earthquake eq;
eq.prevString="PREVIOUS STRING";
eq.magString = "50";
eq.postString = "POST STRING";
printf("\n%s",eq.prevString);
printf("\n%s",eq.magString);
printf("\n%s\n",eq.postString);
}
When I try to run this I get a segmentation fault, which I stop getting if I comment out the struct initialization. You might be able to tell with what I have commented out, but once I get this working I'm trying to make a struct array at which point I know the eq needs to be an Earthquake pointer but I can't even get this working.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <stddef.h>
//#include <paths.h>
struct Earthquake
{
char *prevString;
char *magString;
char *postString;
};
int main()
{
int numLines = 0;
FILE *fileA = fopen("./all_month.csv", "r");
char c[1];
do
{
*c = fgetc(fileA);
//printf("%c", c);
}while(*c != '\n');
do
{
*c = fgetc(fileA);
//printf("%c", c);
if(*c == '\n')
{
numLines++;
}
}while(*c != EOF);
//printf("%d",numLines);
fclose(fileA);
FILE *fileB = fopen("./all_month.csv", "r");
char prevStringTemp[60];
char postStringTemp[150];
char magStringTemp[10];
struct Earthquake eq;
//if(NULL == (entries = (Earthquake *)malloc(sizeof(Earthquake) * numLines)));
//printf("\nmalloc failed\n");
do
{
*c = fgetc(fileB);
//printf("%c", c);
}while(*c != '\n');
char line[200];
int commaCount = 0;
do{
*c = fgetc(fileB);
if(*c==',')
{
commaCount++;
//printf("\n%d", commaCount);
}
strcat(prevStringTemp, c);
}while(commaCount<4);
do
{
*c = fgetc(fileB);
strcat(magStringTemp, c);
}while(*c!=',');
do
{
*c = fgetc(fileB);
strcat(postStringTemp, c);
}while(*c!='\n');
//strcpy(entries[0].prevString, prevString);
//printf(entries[0].prevString);
//fscanf(fileB,"%s",line);
//printf("\n%s\n", line);
fclose(fileB);
//free(entries);
return 0;
}
This is the problem
strcat(prevStringTemp, c);
beacause strcat() expects nul terminated strings which niether the parameters is in your case.
Your c array should be
char c[2] = {0};
and the first element of these
char prevStringTemp[60];
char postStringTemp[150];
char magStringTemp[10];
should be initialized to '\0', like this
prevStringTemp[0] = '\0';
postStringTemp[0] = '\0';
magStringTemp[0] = '\0';
after fixing this, strcat() will behave as you expect.
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define SUCCESS 0
#define FAILURE -1
int str_rev(char **s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(**s != '\0'){
**s++;count++;
}
while(count > 0){
**d++ = **s--;count--;
}
**d = '\0';
return SUCCESS;
}
}
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b;
b = malloc((strlen(a) * sizeof(*a)) + 1);
ret_val = str_rev(&a,&b);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
I am writing a simple program without the use of predefined function for string reversal. But this throws me a segmentation fault. I beleive i'm accessing the correct memory address.
EDITED:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define SUCCESS 0
#define FAILURE -1
int str_rev(char *s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;count++;
}
s--;
while(count > 0){
printf("\n *s:%c \n",*s); // prints the values correctly in the reverse order
*(*d)++ = *s--;count--;
printf("\n **d:%c \n",*((*d)-1)); // doesnt print the values, after the assignement
}
**d = '\0';
printf("\n s:%s *d:%s \n",s,*d); // both s and d doesnt print the values copied
return SUCCESS;
}
}
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b,*x;
b = malloc((strlen(a) * sizeof(*a)) + 1);
x = b;
if(b == NULL){
}
ret_val = str_rev(a,&b);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
I changed the code as above, as 'a' contains the string. hence a single pointer is enough to point to that location as no changes needs to be done. But even after this above change The contents in 's' are not getting copied to 'd'. And i'm getting a seg fault after printing "printf("\n b:%s \n",b);" .
In addition to memory allocation problem also second problem in your code:
First
after your copy loop:
while(count > 0){
**d++ = **s--;count--;
}
You do not terminate d string ny null
add
**d= '\0';
Second: after your first loop
while(**s != '\0'){
**s++;count++;
}
You copy from Null do destination first char become '\0' then how you can print using %s
you should decrements s to point back to last char instead of null char. by --s.
Third
memory allocation do like:
char *a = "angus";
char *b;
b = malloc(strlen(a)*sizeof(*a) + 1);
don't forget to free() memory for b
Four
Next is you forgot to return return SUCCESS; from str_rev()
Firth
you are passing pointer to pointer that change the b and 's' value it self in calling function. When you call with &s and modifies s then no string points to "angus" string.
Do like below I coded you logic using single pointer instead.
int str_rev(char *s, char *d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;
count++;
}
count;
--s;
while(count > 0){
*d = *s;
// printf("\n %c %c", *d, *s);
d++ ;
s--;
count--;
}
*d = '\0';
}
return SUCCESS;
}
in main just call as:
ret_val = str_rev(a, b);
EDIT: Second Code
I notice you are not happy with my suggestion to use single pointer for both!
Well in your second (EDIT) there are some repeating errors:
(1): From function str_rev() your again forgot to return SUCCESS.
(2): Your syntax for str_rcv function is int str_rev(char *s, char **d), first argument is char* but in main() you call it like ret_val = str_rev(&a,&b); that is wrong incompatibly pointer assignment. you should call like:
ret_val = str_rev(a, &b);
(3): IMPORTANT FOR YOU: In second argument you are passing &b Where as in str_rev() function you are updating d pointer hence updating b to which you allocated memory through malloc(), You can't do that!
This will cause an error also: memory clobbered before allocated block
You should rectify your code to call like this: (read comments please)
b = malloc((strlen(a) * sizeof(*a)) + 1);
if(b == NULL){
return FAILURE; // added this line too
}
char* x = b; // first assign b to x, notice x and b are of
// same type char*
ret_val = str_rev(a,&x); // know pass &x instead of &b
(4): although my previous code also working get new version too:
#define SUCCESS 0
#define FAILURE -1
int str_rev(char *s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;count++;
}
s--;
while(count > 0){
*(*d)++ = *s--;
printf("\n *s:%c And **d: %c\n",*(s+1), *((*d)-1)); // for bug finding
// because s decremented and d incremented
count--;
}
**d = '\0';
return 0;
}
}
the main function():
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b;
b = malloc((strlen(a) * sizeof(*a)) + 1);
if(b == NULL){
return -1;
}
char* x = b;
ret_val = str_rev(a,&x);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
Its working Output is:
*s:s And **d: s
*s:u And **d: u
*s:g And **d: g
*s:n And **d: n
*s:a And **d: a
b:sugna
Here your running code at Codpad
Here:
**s++
you are incrementing the char ** s. This alters it to point to the next char * which is not meaningful in your program.
Because of operator precedence, **s++ is the same as (*(*(s++)). Which is to say, it returns the value of the char pointed to by the char * pointed to by s, and as a side-effect increments s to point to the 'next' char * (which isn't well-defined because you do not have an array of char *s).
A typical idiom in C string manipulation is *p++, which is the same as (*(p++)). This returns the value of the char pointed to by p and as a side effect sets p to point to the next char, which would be the next character in the string. To do the same with a char ** one must write *(*p)++, or more explicitly (*((*p)++)).
Also, it is not necessary to use char **s to reverse a string; it can be done with only char *s.
In this line
b = malloc(sizeof(b));
sizeof(b) is just the size of a pointer and that is not ehough to fit a whole string.
Either pass the size you want to malloc
b = malloc(42);
b = malloc(strlen(a) + 1);
or change b into an array instead of a pointer
char b[42];
Other than that, I would highly recommend learing to use tools like gdb or valgrind to debug these segmentation faults. At the least they will tell you what line is segfaulting and just that will help a lot.
Change ret = str_rev(&a,&b); to ret_val = str_rev(&a,&b);
Please find a reworked function as below
int str_rev(char **sinp, char **dout){
int count = 0;
char *s = *sinp; // Dereference the starting address of source
char *d = *dout; // Dereference the starting address of destination
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
*s++;count++;
}
s--; // Requires a decrement as it is pointing to NULL
while(count > 0){
*d++ = *s--;
count--;
}
}
*d = '\0'; // Need a NULL terminator to convert it to string
return SUCCESS; // Requires a return as all branches of function should return values
}
char str[] = "hello";
char *foo = foo;
*foo++ is the equivalent to *(foo++), not (*foo)++. foo++ causes foo to point to the next char.
char str[] = "hello";
char *foo = str;
char **bar = &foo;
**bar++ is the equivalent to **(bar++);, not (**bar)++. bar++ causes bar to point to the next char *... Do you see a problem?
(*bar)++ causes foo to point to the next char. consider what you'd be doing to your caller's a and b variables in ret_val = str_rev(&a,&b);, (*s)++; and (*d)++.
I need the send and integer to a function and then append that to the end of a constant character.
int main (void)
{
append(1);
}
int append(int input)
{
const char P = 'P';
//This where I want to append 1 to P to create "P1"'
}
No matter what you do, you need to convert the number to a string, otherwise you can't create a string containing both numbers.
You can actually combine both the concatenation and the int-to-string conversion in one function call: sprintf:
char output[16];
sprintf(output, "P%d", input);
I'm not an expert on C, but I don't believe constants should be changed once they are defined.
Not sure if you can add something to a const chat (since its a const).
But why not:
char p[3];
sprintf(p, "P%d",input);
You cannot assign more than one character value to a char. For doing that you would have to take a string. Maybe like this.
int append(int input)
{
const char P = 'P';
//This where I want to append 1 to P to create "P1"
char app[2] ; //extend that for your no. of digits
app[0] = P '
app[1] = (char) input ;
}
This is for one digit. You can allocate dynamic memory for big integers and do the same in a loop.
What about using strncat?
See a working example on codepad: http://codepad.org/xdwhH0ss
I would convert the number to a string (assuming you have access to a function called itoa in this example and concatenate it to the character. If you don't have access to itoa you could sprintf instead.
itoa method:
#include <stdio.h>
#include <stdlib.h>
char *foo(const char ch, const int i)
{
char *num, *ret;
int c = i;
if(c <= 0) c++;
if(c == 0) c++;
while(c != 0)
{
c++;
c /= 10;
}
c += 1;
if(!(num = malloc(c)))
{
fputs("Memory allocation failed.", stderr);
exit(1);
}
if(!(ret = malloc(c + 1)))
{
fputs("Memory allocation failed.", stderr);
free(num);
exit(1);
}
itoa(i, num, 10);
ret[0] = ch;
ret[1] = 0x00;
strcat(ret, num);
free(num);
return ret;
}
int main(void)
{
char *result;
if(!(result = foo('C', 20))) exit(1);
puts(result);
free(result);
return 0;
}
sprintf method:
#include <stdio.h>
#include <stdlib.h>
char *foo(const char ch, const int i)
{
char *num, *ret;
int c = i;
if(c <= 0) c++;
if(c == 0) c++;
while(c != 0)
{
c++;
c /= 10;
}
c += 1;
if(!(num = malloc(c)))
{
fputs("Memory allocation failed.", stderr);
exit(1);
}
if(!(ret = malloc(c + 1)))
{
fputs("Memory allocation failed.", stderr);
free(num);
exit(1);
}
sprintf(num, "%d", i);
ret[0] = ch;
ret[1] = 0x00;
strcat(ret, num);
free(num);
return ret;
}
int main(void)
{
char *result;
if(!(result = foo('C', 20))) exit(1);
puts(result);
free(result);
return 0;
}
I compiled and tested both of these and they seem to work quite nicely. Good luck.