I have a struct:
typedef struct myStruct {
char** a;
char** b;
} myStruct;
I am trying to read from stdin and initialize an array of myStruct*
int main() {
int maxlength = 60 + 1;
int arraySize = 2;
myStruct** myArray = (myStruct*) malloc(sizeof(myStruct*) * arraySize);
int runningIndex = 0;
while(1) {
char* aline = (char*) malloc(maxlength);
int status = getline(&aline, &maxlength, stdin);
if(status == -1)
break;
char* bline = (char*) malloc(maxlength);
getline(&bline, &maxlength, stdin);
if(runningIndex == arraySize) {
arraySize *= 2;
myArray = realloc(myArray, sizeof(myStruct*) * arraySize);
}
myArray[runningIndex] = (myStruct*) malloc(sizeof(myStruct*));
myArray[runningIndex]->a = &aline;
myArray[runningIndex]->a = &bline;
runningIndex++;
}
for(int i = 0; i < runningIndex; i++) {
printf("outside the loop at index %d, a is %s and b is %s", i, *myArray[i]->a, *myArray[i]->b);
}
}
I did a few printf within the while to confirm that each myStruct is successfully created with the strings from stdin. However, outside the loop, all the stored values seems to be gone. I was thinking about scope but could not figure out why. Could someone explain how I shall do this properly? Thanks!
sample to fix :
#include <stdio.h>
#include <stdlib.h>
typedef struct myStruct {
char *a;
char *b;
} myStruct;
int main() {
int maxlength = 60 + 1;
int arraySize = 2;
myStruct* myArray = malloc(sizeof(myStruct) * arraySize);
int runningIndex = 0;
while(1) {
char *aline = malloc(maxlength);
int status = getline(&aline, &maxlength, stdin);
if(status == -1)
break;
char *bline = malloc(maxlength);
getline(&bline, &maxlength, stdin);
if(runningIndex == arraySize) {
arraySize *= 2;
myArray = realloc(myArray, sizeof(myStruct) * arraySize);
}
myArray[runningIndex].a = aline;//&aline is address of local variable.
myArray[runningIndex].b = bline;//And content is rewritten in each loop.
runningIndex++;
}
for(int i = 0; i < runningIndex; i++) {
printf("outside the loop at index %d, a is %s and b is %s", i, myArray[i].a, myArray[i].b);
}
//deallocate
return 0;
}
A single string pointer is defined like this:
char *pStr;
An array of string pointers is defined like this:
char **pStrArr;
To dynamically create memory for a single string, do this:
pStr = malloc(STRING_LEN);
To dynamically create memory for an array of strings, do this:
pStrArr = (NUM_STRINGS * (*pStrArr));
for(str = 0; str < NUM_STRINGS; str++)
pStrArr[str] = malloc(STRING_LEN);
In your case, you'd need to create either two char strings for your struct or two arrays of char strings, whatever your requirements are. It looks like you really only need two single strings. If so, do this:
typedef struct
{
char* a;
char* b;
} myStruct;
myStruct structure;
structure.a = malloc(STRING_LEN);
structure.b = malloc(STRING_LEN);
Related
I am using bsearch with a key value equivalent to an array element thats value is a pointer. The key is the elements of an array thats an array of character pointers. I dont think you can dereference array element value by indexing and use value as pointer to char string. I tried casting element value to (char *) but that did not work. Im getting garbage for return value of bsearch.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int Compare(const void *elemA, const void *elemB){
return strcmp(*(char **)elemA, *(char **)elemB);
}
void SortStudents(const char *studentList[], size_t studentCount){
qsort(studentList, studentCount, sizeof(studentList[0]), Compare);
}
void DisplayClassStatus(const char *registrants[], size_t registrantCount,
const char *attendees[], size_t attendeeCount) {
int counter;
int *regnotattend_status = (int *)malloc(sizeof(int) * registrantCount);
int *attendeenotreg_status = (int *)malloc(sizeof(int) * attendeeCount);
char *attendeeStatus, *registrantstatus;
for ( counter = 0; counter < (int)registrantCount; counter++) {
attendeeStatus = (char *) bsearch(®istrants[counter], attendees,
attendeeCount, sizeof(attendees[0]), Compare);
if (attendeeStatus == NULL)
regnotattend_status[counter] = 0;
else{
regnotattend_status[counter] = 1;
printf(" attendeestatus = %s \n", attendeeStatus);
}
}
for (counter = 0; counter < (int)attendeeCount; counter++){
registrantstatus = (char *)bsearch(&attendees[counter], registrants,
registrantCount, sizeof(registrants[0]), Compare);
if ( registrantstatus == NULL)
attendeenotreg_status[counter] = 0;
else
attendeenotreg_status[counter] = 1;
printf("registrantstatus = %s \n", registrantstatus);
}
printf(" Not present: \n");
for ( counter = 0; counter < (int)registrantCount; counter++) {
if (regnotattend_status[counter] == 0)
printf(" %s \n", registrants[counter]);
}
printf( "\n");
printf(" Not registered: \n");
for ( counter = 0; counter < (int)attendeeCount; counter++) {
if (attendeenotreg_status[counter] == 0)
printf(" %s \n", attendeenotreg_status[counter]);
}
}
Since input array is of type const char* [], return value of bsearch would be const char**. Here is your modified code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int Compare(const void *elemA, const void *elemB){
return strcmp(*(char **)elemA, *(char **)elemB);
}
void SortStudents(const char *studentList[], size_t studentCount){
qsort(studentList, studentCount, sizeof(studentList[0]), Compare);
}
void DisplayClassStatus(const char *registrants[], size_t registrantCount,
const char *attendees[], size_t attendeeCount) {
int counter;
int *regnotattend_status = (int *)malloc(sizeof(int) * registrantCount);
int *attendeenotreg_status = (int *)malloc(sizeof(int) * attendeeCount);
char **attendeeStatus, **registrantstatus;
for ( counter = 0; counter < (int)registrantCount; counter++) {
attendeeStatus = (char **) bsearch(®istrants[counter], attendees,
attendeeCount, sizeof(attendees[0]), Compare);
if (attendeeStatus == NULL)
regnotattend_status[counter] = 0;
else{
regnotattend_status[counter] = 1;
printf(" attendeestatus = %s \n", *attendeeStatus);
}
}
for (counter = 0; counter < (int)attendeeCount; counter++){
registrantstatus = (char **)bsearch(&attendees[counter], registrants,
registrantCount, sizeof(registrants[0]), Compare);
if ( registrantstatus == NULL)
attendeenotreg_status[counter] = 0;
else {
attendeenotreg_status[counter] = 1;
printf("registrantstatus = %s \n", *registrantstatus);
}
}
}
int main(int argc, char **argv) {
(void)argc, (void)argv;
const char *attendies[] = {
"foo", "bar", "foobar"
};
const char *registrants[] = { "bar" };
SortStudents(attendies, 3);
DisplayClassStatus(registrants, 1, attendies, 3);
return 0;
}
Last loops are removed since it have a format error (as pointed in comment by WhozCraig) and I'm not really grasp what it meant to do, and it isn't relevant to the question. Please also note that you didn't free memory that you've allocated with malloc.
For possible future questions, please include complete use case whenever possible (somehting like what I've made up in main function).
I am trying to extends my Ruby code with a C functions. The C code compiles without warning. But When I try to run the ruby code, I got a segmentation fault:
I have this c code:
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nessie.h"
/* #define TRACE_INTERMEDIATE_VALUES */
/*
* The number of rounds of the internal dedicated block cipher.
*/
#define R 10
VALUE rb_mExample;
VALUE rb_cClass;
// ...
static char* displayHash(const unsigned char array[], int length){
int i, k;
char *str;
str = malloc(3 * length + 1);
if (str == NULL) {
return NULL;
}
k = 0;
str[0] = '\0';
for (i = 0; i < length; i++){
char hex[3];
if (i % 32 == 0){
str[k++] = ' ';
}
if (i % 8 == 0){
str[k++] = ' ';
}
snprintf(hex, sizeof(hex), "%02X", array[i]);
str[k++] = hex[0];
str[k++] = hex[1];
}
str[k] = '\0';
return str;
}
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
return (VALUE) displayHash(digest, DIGESTBYTES);
}
void
Init_example(){
rb_mExample = rb_define_module("Example");
rb_cClass = rb_define_class_under(rb_mExample, "Class", rb_cObject);
rb_define_method(rb_cClass, "print_string", print_string, 1);
}
and this Ruby code:
require "example"
def print
e = Example::Class.new
e.print_string("ruby")
end
When I run the ruby code, I got a segmentation fault.
EDIT: gist with log info
https://gist.github.com/psantos10/f07484afa26ce0e55181
Where I failing? I am new in C language.
EDIT:
I changed my "print_string" to look like this:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}
whith that, segmentation fault gone. But the string returned is coming with a strange characters like:
"ruby\x00\x00\x00\x00\x00No error detected.\x00\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD80x\xC0\x18`\x18\x18&F\xAF\x05#\x8C##\xB8\x91\xF9~\xC6?\xC6\xC6\xFB\xCDo\x13\xE8\x87\xE8\xE8\xCB\x13\xA1L\x87&\x87\x87\x11mb\xA9\xB8\xDA\xB8\xB8\t\x02\x05\b\x01\x04\x01\x01\r\x9EnBO!OO\x9Bl\xEE\xAD6\xD866\xFFQ\x04Y\xA6\xA2\xA6\xA6\f\xB9\xBD\xDE\xD2o\xD2"
When the correct must be only:
"ruby"
EDIT 3:
Making this change:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
/*
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
*/
NESSIEinit(&w);
NESSIEadd((u8*)"ruby", 8*4, &w);
NESSIEfinalize(&w, digest);
return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}
the correct value are returned.
Then I try to to that:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
/*
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
*/
NESSIEinit(&w);
NESSIEadd((u8*)"ruby", 8*4, &w);
NESSIEfinalize(&w, digest);
return rb_str_new2(valor);
}
Expecting "ruby" string to be returned. But not. It returns: "\x05"
What that mean?
for (i = 0; i < length; i++)
Inside this loop for each passing if condition you increment k so by doing this you will be having array out of bound access hence the crash.
Make sure the
char *str = malloc( 3 * length + 1);
is not
char *str = malloc( 3 * (length + 1));
For Eg:
Have value of length = 2;
char *str = malloc(7);
Now in the for loop you increment k 4 times.
k = 4;
Now after the second iteration if you exit the loop then
k=8;
So str[8] is not a valid access and might lead to crash
Before all, let me thanks #FrederickCheung for give me the right direction.
The solution code is:
VALUE
print_string(VALUE class, VALUE valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
VALUE info;
// Note here I must convert the Ruby VALUE type to C type. Thats is the trick.
char* valor2 = RSTRING_PTR(valor);
int i;
for (i = 0; valor2[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor2, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
info = rb_str_new_cstr(displayHash(digest, DIGESTBYTES));
return info;
}
For who want to see where this code was used, can access: https://github.com/AngoDev/kryptonita
What is the right way to initialize char** ?
I get coverity error - Uninitialized pointer read (UNINIT) when trying:
char **values = NULL;
or
char **values = { NULL };
This example program illustrates initialization of an array of C strings.
#include <stdio.h>
const char * array[] = {
"First entry",
"Second entry",
"Third entry",
};
#define n_array (sizeof (array) / sizeof (const char *))
int main ()
{
int i;
for (i = 0; i < n_array; i++) {
printf ("%d: %s\n", i, array[i]);
}
return 0;
}
It prints out the following:
0: First entry
1: Second entry
2: Third entry
Its fine to just do char **strings;, char **strings = NULL, or char **strings = {NULL}
but to initialize it you'd have to use malloc:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
// allocate space for 5 pointers to strings
char **strings = (char**)malloc(5*sizeof(char*));
int i = 0;
//allocate space for each string
// here allocate 50 bytes, which is more than enough for the strings
for(i = 0; i < 5; i++){
printf("%d\n", i);
strings[i] = (char*)malloc(50*sizeof(char));
}
//assign them all something
sprintf(strings[0], "bird goes tweet");
sprintf(strings[1], "mouse goes squeak");
sprintf(strings[2], "cow goes moo");
sprintf(strings[3], "frog goes croak");
sprintf(strings[4], "what does the fox say?");
// Print it out
for(i = 0; i < 5; i++){
printf("Line #%d(length: %lu): %s\n", i, strlen(strings[i]),strings[i]);
}
//Free each string
for(i = 0; i < 5; i++){
free(strings[i]);
}
//finally release the first string
free(strings);
return 0;
}
There is no right way, but you can initialize an array of literals:
char **values = (char *[]){"a", "b", "c"};
or you can allocate each and initialize it:
char **values = malloc(sizeof(char*) * s);
for(...)
{
values[i] = malloc(sizeof(char) * l);
//or
values[i] = "hello";
}
I had my program printing out the words in a file and incrementing when they appeared more than once. I am now getting just "NULL" and the count as "17" instead. I can't find anything that I changed but am not sure if it is because I haven't figured out how to properly free up my arrays.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BASE 5
#define MAX 50
typedef char *string;
struct wordCount
{
string word;
unsigned int count;
};
int main (void)
{
unsigned int i;
unsigned int found;
unsigned int arraysize;
unsigned int newsize;
char temp [40];
struct wordCount* wordArray;
FILE *infile;
arraysize = 0;
infile = fopen("input.txt","r");
wordArray = malloc(BASE * sizeof(struct wordCount));
/*store in word from infile to struct, increment counter each time it appears*/
while (fscanf(infile, "%s", temp) == 1) {
found = 0;
for (i = 0; i < arraysize; i++){
if(strcmp(temp,wordArray[i].word) == 0){
wordArray[i].count++;
found++;
}
}
if (found== 0){
if (arraysize<BASE){
wordArray[arraysize].word = (char
*)malloc((strlen(temp)+1) * sizeof(char));
strcpy(wordArray[arraysize].word,temp);
wordArray[arraysize].count = 1;
arraysize++;
} else {
wordArray = realloc(wordArray, arraysize * sizeof(struct wordCount));
wordArray[arraysize].word = (char *)malloc((strlen(temp)+1) *
sizeof(char));
strcpy(wordArray[arraysize].word,temp);
wordArray[arraysize].count = 1;
arraysize++;
}
}
}
fclose(infile);
/*newsize = SearchAndDestroy(wordArray, arraysize); */
for (i = 0; i < arraysize; i++) {
printf("%s ", wordArray[arraysize].word);
printf("%d\n", wordArray[arraysize].count);
/*free(wordArray[i].word);*/
}
/* and when done:*/
free(wordArray);
return 0;
}
You aren't tracking things properly. You need to pay more attention to the fact that "How many words I have", "how many words I have room for", and "how many words I would like to have room for" are three distinct items that need to all be tracked separately. In particular, it doesn't look like your call to realloc() is correct.
I receive a pointer numeric value like: 0xbfe0e6ac it is possible set int foo for example to value of 0xbfe0e6ac that is another int in memory?
My scenario:
I am tried to implement functions for get next index from array passing the pointer value (like the above example) as parameter.
For example:
char * a = "baa";
char* b = "foo";
printf("%c", cgetnext(&a)); // b
printf("%c", cgetnext(&a)); // a
printf("%c", cgetnext(&b)); // f
printf("%c", cgetnext(&b)); // a
The single way that I can see to do this is: in cgetnex() save pointer of array passed like parameter into array and each call, check if the array passed as paramater was used before and get information of it, like lasindexused and pointer value into RAM.
Here is my code:
#include <string.h>
#include <stdlib.h>
typedef struct { int pLocation; int lastIndex; } POINTERINFORMATION;
int __myIndex;
POINTERINFORMATION pointersLocations[256];
int pointersLocationsLength;
char * temparr = NULL;
__myIndex = pointersLocationsLength = 0;
int
plAdd (int p)
{
if (plLen >= sizeof(pointersLocation)) {
return -1;
} else {
pointersLocation[pointersLocationsLength].pLocation = p;
pointersLocation[pointersLocationsLength].lastindex = 0;
pointersLocationsLength ++;
return pointersLocationsLength;
}
}
int
getPointer (int p, POINTERINFORMATION ** out)
{
int i;
for (i = 0; i < pointersLocationsLength; i++)
{
if(pointersLocation[pointersLocationsLength].pLocation == p)
{
*out = makevariablefromponiter(pi.pLocation);
return 1;
}
}
return 0;
}
char
cgetnext(char * arr)
{
char * myarr;
const size_t size = sizeof(char *) + 1;
myarr = malloc(size);
if (NULL == arr){
POINTERINFORMATION * pi;
if (getPointer(p, &pi))
{
__myIndex = pi.lastindex;
myarr = makevariablefromponiter(pi.pLocation);
}
} else {
myarr = strdup (arr);
}
if (strlen(myarr) == __myIndex) {
return '\0';
} else {
__myIndex ++;
temparr = malloc(size);
temparr = strdup(myarr);
return myarr[__myIndex - 1];
}
}
Yes, do something like this:
int *fooPtr = 0xbfe0e6ac;
foo = *fooPtr;
In fact, you can make it even more concise:
foo = *(int *) 0xbfe0e6ac;