I m reallocating a char** array with every entry and while compiling comes back clean, only the first entry is stored and I get Segmentation fault (core dumped) always when i try to register a 4th entry.
Here is the relevant code in main.c:
int main(int argc, char *argv[])
{
int i,sizea,sizeb,choice,letters,check,mistakes,count;
char C[26][2];
char **A,**B,a;
A=(char**)malloc(sizeof(char*));
*A=(char*)malloc((MAX_CHAR+1)*sizeof(char));
sizea=1;
build(&A,&sizea);
return 0;
}
And here is the implementation of the method in mylib.c:
void build(char ***A, int *sizea)
{
*A=(char**)realloc(*A,(*sizea) * sizeof(char*));
*A[*sizea-1]=(char*)malloc((MAX_CHAR+1)*sizeof(char));
printf("Give word :");
scanf("%s",(*A[*sizea-1]));
(*sizea)++;
}
Thanks a lot for your help.
edit: similar problems in this method that werent fixed by doing the same thing
void find(char **A, char ***B, int letters,int sizea, int *sizeb){
int i,j,k,dummy;
char a='a';
for(i=0;i<(sizea-1);i++){
printf("here\n");
if(A[i][letters]=='\0'){
*B=(char**)realloc(*B,(*sizeb+1) * sizeof(char*));
(*B)[*sizeb]=(char*)malloc((letters+1)*sizeof(char));
(*B)[*sizeb-1]=A[i];
*sizeb++;
printf("%s\n", (*B)[i]);
}
}
}
The problem is here:
scanf("%s",(*A[*sizea-1]));
The array index operator [] has higher precedence than the dereference operator *. So the above parses as:
scanf("%s",(*(A[*sizea-1])));
What you want is:
scanf("%s",((*A)[*sizea-1]));
Similarly, this:
*A[*sizea-1]=(char*)malloc((MAX_CHAR+1)*sizeof(char));
Should be:
(*A)[*sizea-1]=(char*)malloc((MAX_CHAR+1)*sizeof(char));
Related
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 5 years ago.
I was writing a program in c for vignere cipher, when in a function to generate the key as the same length of input name,i encountered a bug where if i remove the "printf" line displaying the length of input string it, prints weird stuff on the sceen, it happens only when i delete that "printf" line from the GenKey() function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *GenKey(char *key, char *source){
int i=0,j=0;
char ReturnKey[strlen(source)];
printf("%d\n",strlen(source)); // THIS LINE HERE CAUSES PROBLEM
for(i=0;i<strlen(source)-1;i++){
if(j==strlen(key)){
j=0;
}
ReturnKey[i]=key[j];
j++;
}
return ReturnKey;
}
int main()
{
int i;
char name[10000];
char container[10000];
char VigKey[]="INFERNO";
char *NamePtr;
char *KeyPtr;
printf("give a name: ");
fgets(name,10000,stdin);
char GeneratedKey[strlen(name)];
KeyPtr=VigKey;
NamePtr=name;
strcpy(GeneratedKey,GenKey(KeyPtr,NamePtr));
printf("%s",GeneratedKey);
}
Output(Before deleting that line):
give a name: ATTACKATDAWN
13
INFERNOINFER
Now i delete that line
char *GenKey(char *key, char *source){
int i=0,j=0;
char ReturnKey[strlen(source)];
// NOW I HAVE DELETED THAT LINE
for(i=0;i<strlen(source)-1;i++){
if(j==strlen(key)){
j=0;
}
ReturnKey[i]=key[j];
j++;
}
return ReturnKey;
}
Output(After deleting that line):
give a name: ATTACKATDAWN
INFERNOINFERα╫`
Try creating the ReturnKey character array on the heap with malloc like this:
char *GenKey(char *key, char *source){
int i=0,j=0;
char *ReturnKey = malloc(sizeof(char) * strlen(source));
for(i=0;i<strlen(source)-1;i++){
if(j==strlen(key)){
j=0;
}
ReturnKey[i]=key[j];
j++;
}
return ReturnKey;
}
Before when you were creating ReturnKey, you were doing so as a local variable which only lives in the context of that function. Even though you would see your word still there, that was just because it was still in that position in memory but was no longer being referencing by an object.
When you create a dynamic array with a function like malloc, you are creating it on the so called "heap" which doesn't get released when it goes out of scope, this way you can return it from the function (you actually return a pointer to that location in memory).
When using malloc note that the memory IS NOT RELEASED, and thus you must at some point later release it yourself by calling free otherwise you will leak memory.
This is what the full code might look like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *GenKey(char *key, char *source){
int i=0, j=0;
// malloc takes the size of the data type * the length
char *ReturnKey = malloc(sizeof(char) * strlen(source));
for(i=0;i<strlen(source)-1;i++){
if(j==strlen(key)){
j=0;
}
ReturnKey[i]=key[j];
j++;
}
return ReturnKey;
}
int main()
{
int i;
char name[10000];
char container[10000];
char VigKey[]="INFERNO";
char *NamePtr;
char *KeyPtr;
printf("give a name: ");
fgets(name,10000,stdin);
KeyPtr=VigKey;
NamePtr=name;
char *GeneratedKey = GenKey(KeyPtr,NamePtr);
printf("%s",GeneratedKey);
free(GeneratedKey); // IMPORTANT!!!
}
Here is a more in depth article on using malloc and free:
https://www.codingunit.com/c-tutorial-the-functions-malloc-and-free
I decided to try to make a concatenating function as strcat doesn't work for chars, only strings.
#include <stdio.h>
#include <string.h>
char concat(char a[], char b[]);
int main ()
{
char *con = concat("hel", "lo");
return(0);
}
char concat(char a[], char b[]){
int lena = strlen(a);
int lenb = strlen(b);
char con[lena+lenb];
con[0] = a;
con[lena] = b;
printf("%s", con);
return con;
}
This code prints "Ã…ÃÆ". Not sure where I am going wrong?
Thanks
First, you shouldn't return reference to temporary
char con[lena+lenb];
(note that the garbage you get doesn't come from that since you print within the function)
Second, you don't allocate enough memory: should be (with first problem fixed):
char *con = malloc(lena+lenb+1);
then use strcpy/strcat anyway, it's faster, and your original code doesn't do anything useful (mixing chars with array of chars & the size of the arrays isn't known at this moment: that's the reason of the garbage you're getting):
strcpy(con,a);
strcat(con,b);
Or as some suggest that they're unsafe functions, and since we know the size of inputs we can write:
memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);
Also: the prototype of concat is really wrong. It should be:
char *concat(const char *a, const char *b){
(as it returns a pointer on chars not a char. And the arguments should be constant pointers so you can use your function with any string)
and you're done (don't forget to free the string when you're done with it)
Fixed code (tested, surprisingly returns hello, maybe because it compiles without errors with gcc -Wall -Wwrite-strings -Werror. My advice: turn the warnings on and read them. You'll solve 80% of your problems that way):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *concat(const char *a, const char *b);
int main ()
{
char *con = concat("hel", "lo");
printf("%s\n",con);
return(0);
}
char *concat(const char *a, const char *b){
int lena = strlen(a);
int lenb = strlen(b);
char *con = malloc(lena+lenb+1);
// copy & concat (including string termination)
memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);
return con;
}
I am constantly getting "Segmentation fault (Core dumped)" error in the following c program. Please help me debug the program.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
int numcmp(const char *a,const char *b){
if(atoi(a)==atoi(b)) return 0;
return -1;
}
int isequal(char *a,char *b,int (*cmp)(const char *,const char *)){
if(!cmp(a,b)) return 1;
return 0;
}
int main(int argc,char *argv[]){
if(argc!=3){
puts("Usage: Compare two string alphabeticaly or numericaly");
printf("Syntax: %s string1 string2\n",argv[0]);
exit(-1);
}
if(isequal(argv[1],argv[2],isalpha(argv[1])?strcmp:numcmp))
printf("%s and %s are equal\n",argv[1],argv[2]);
else
printf("%s and %s are not equal\n",argv[1],argv[2]);
}
isalpha only works for chars, not whole strings. You could write a function for that:
/* 1 - only letters, 0 - other characters */
int str_isalpha(const char* str) {
while (*str)
if (!isalpha(*(str++)))
return 0;
return 1;
}
and then use it appropriately. But actually, I don't see a reason for using numcmp here at all. Comparing ints and const char*s should yield the similar results.
I am having a problem with this code, this code is a encryption for a rail cipher and if you enter in an input "testing" you should get an output "tietnsg" which i do get.
However if i change the input to "testingj" i get an output of "tietnjsgp?²!lj" i can see from my debugging the "?²!lj" appears to be tagged on during the last fill in the toCipher function
does anyone know how to fix it other than the way that i did it?
/*
CIS Computer Secutrity Program 1
10-10-14
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
char *toCipher(char **arr,int x,int y);
char *Encrypt(char *pT, int size);
char **create(int x,int y);
void FreeArr(char **array, int y);
void print(char *word,int strl);
int main(){
char pt[]= "testingj";
char *word = Encrypt(pt,3);
print(word, sizeof(pt));
free(word);
}
/*
Take in a pointer to a word, and the lenght of the string
Post print each char in the array, (used beacuase i had some issues with the memory, i keep getting extra adresses
*/
void print(char *word,int strl){
int i;
for(i=0;i<strl-1;i++){
printf("this is correct %c",word[i]);
}
printf("\n");
}
/*
Pre, take in the pointer to the plain text word to be encrypted as well as the depth of the Encryption desired
Post: Construct the array, insert values into the 2d array, convert the 2d array to a 1d array and return the 1d array
*/
char *Encrypt(char *word,int y){
int x = strlen(word);
int counter=0;
int ycomp=0;
int rate=1;
char **rail = create(x,y);
while(counter<x){
if(ycomp==y-1){
rate=-1;
}
if(ycomp==0){
rate=1;
}
rail[counter][ycomp]=word[counter];
ycomp=ycomp+rate;
counter++;
}//end of rail construction
char *DrWord = toCipher(rail,x,y);
FreeArr(rail,y);
return(DrWord);
}
/*
Create a dynamic 2d array of chars for the rail cypher to use
Take in the dimensions
return the pointer of the rails initial address, after it created the space for the rail
*/
char *toCipher(char **arr,int x,int y){
int xI =0;
int yI=0;
int counter =0;
char *word = (char*)malloc(x);
int i;
for(yI=0;yI<y;yI++){
for(xI=0;xI<x;xI++){
if(arr[xI][yI]!= 0){
word[counter]=arr[xI][yI];
counter++;
}
}
}
printf("this is the problem %s\n",word);
return(word);
}
char **create(int x, int y){
char **rail;
int i,j;
rail = malloc(sizeof(char**)*x);
for(i=0;i<x;i++){
rail[i]= (char*)malloc(y * sizeof(char*));
}
for(i=0;i<y;i++){
for(j=0;j<x;j++){
rail[j][i]= 0;
}
}
return(rail);
}
/*
Pre, take in a malloc'd array, with the height of the array
free the malloc calls one by one, and finally free the initial adress
*/
void FreeArr(char **array, int y){
int i;
for(i=0;i<y;i++){
free(array[i]);
}
free(array);
}
In toCipher, the word is printed without nul-termination. Either:
char *word = (char*)malloc(x+1); // allocate an extra char for nul.
word[x] = 0; // add the nul at the end.
or:
printf("this is the problem %.*s\n",x,word); // limit characters printed to x.
I forgot to initialize word to 0, the tagged memory if you watch it in debug mode was not being replaced, therefore was tagged along in the newly constructed string
I'm getting this error on line #4 which says 'invalid initializer'. I know what the error means, but I can't work out why i'm getting the error. I've tried all sorts of combinations of pointers and values, but it doesn't seem to want to work. Any help / feedback for the code would be greatly appreciated.
Note: I plan to have a 2D array for the chessboard, which mean 64 ints of memory malloc'd.
The printf is there to keep the compiler happy and show me whether at [4][2] there is a '0'.
int *newBoard();
int main(int argc, char *argv[]) {
int *chessBoard[7][7] = *newBoard();
printf ("%d", chessBoard[4][2]);
return EXIT_SUCCESS;
}
int *newBoard() {
int counter = 0;
int *blankBoard = malloc(sizeof((int) * TOTALSPACES));
while (counter < TOTALSPACES) {
blankBoard[counter] = VACANT;
counter++;
}
return blankBoard;
}
newBoard returns an array of TOTALSPACES ints. int *chessBoard[7][7] = *newBoard(); LHS is a 7x7 array of int pointers (not ints). RHS is what, the contents of of an int pointer returned by the call? (what do you think the * infront of the call to newBoard() is doing?
Either int *newBoard = newBoard(); (to use heap memory) or int newBoard[7][7]; (to use stack memory) would work. You are trying to do half of each!
int *chessBoard[7][7] stands for an 2D array(7*7), each element type is int*;
but *newBoard() stand for an int element.
#include <stdio.h>
#include <stdlib.h>
#define TOTALSPACES 8*8
#define VACANT '0'
void *newBoard();
int main(int argc, char *argv[]) {
int (*chessBoard)[8][8] = newBoard();
printf ("%d", (*chessBoard)[4][2]);//48 : '0'
return EXIT_SUCCESS;
}
void *newBoard() {
int *blankBoard = malloc(sizeof(int) * TOTALSPACES);
int counter = 0;
while (counter < TOTALSPACES)
blankBoard[counter++] = VACANT;
return blankBoard;
}