I am trying to read in a text file, which contains integers, and place them into an array. I will be sorting them once I have the array created. However, I trying to make sure things work as I implement them but I am getting a segmentation fault when I attempt to open a file. I do not understand why.
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE_T_MAX 16777216
/****** FORWARD DECLARATIONS ******/
void die(const char *message) {
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
// ARRAY
typedef struct int_array {
int *array;
size_t length;
size_t capacity;
} int_array;
void int_array_init(int_array *array);
void int_array_free(int_array *array);
void int_array_add(int_array *array, int value);
/****** END OF DECLARATIONS ******/
//
//
/********** MAIN PROGRAM **********/
int main(char argc, char *argv[]) {
// VARIABLES
FILE *data;
int_array numbers;
int_array_init(&numbers);
int i = 0;
char value[10];
// LOAD FILES
printf("Loading files...\n");
data = fopen("list0.txt", "r");
if(data == NULL) die("Failed to load file.");
while(!feof(data) && !ferror(data)) {
fscanf(data, "%s", value);
int_array_add(&numbers, atoi(value));
printf("%d", numbers.array[i]);
i++;
}
// CLEAN UP
int_array_free(&numbers);
fclose(data);
return 0;
}
/*********** END OF MAIN **********/
//
//
/******* ADDITIONAL METHODS *******/
void int_array_init(int_array *array) {
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_free(int_array *array) {
free(array->array);
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_add(int_array *array, int value) {
if (array->length == array-> capacity)
{
int new_capacity;
if (array->capacity == 0) new_capacity = 10;
else new_capacity = array->capacity * 2;
if (new_capacity > array->capacity && new_capacity < SIZE_T_MAX / sizeof(int)) {
int *new_array = realloc(array->array, new_capacity * sizeof(int));
if (new_array != NULL) {
array->array = new_array;
array->capacity = new_capacity;
} else {
die("Out of Memory");
}
} else {
die("Overflow.");
}
}
array->array[array->length] = value;
array->length++;
}
I have corrected and fixed my code. The problem was in the while loop being infinite and corrected with:
while(!feof(data) && !ferror(data))
Related
I'm trying to create a stack using a dynamic array and I'm getting an error when I try to run the DeleteStack() function, however, if I set a breakpoint before the function and run the main program up till that point, then continue past it, it executes properly. Would someone please tell me what I'm doing wrong and why I'm seeing this behavior?
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dynamic_array_stack.h"
int main() {
// create stack
DynArrayStack *S = CreateStack();
// fill stack
for (int i = 1; i <= 10; i++)
Push(S, i);
// try pushing past capacity, no error (realloc's)
Push(S, 42);
// top of stack
printf("Top of stack is %d\n", Top(S));
// pop all elements of stack
while (Top(S) != INT_MIN) {
printf("%d\n", Pop(S));
}
// delete stack, check pointer again
DeleteStack(S);
return 0;
}
dynamic_array_stack.h:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct dynarraystack {
int top;
int capacity;
int *array;
} DynArrayStack;
DynArrayStack* CreateStack() {
DynArrayStack* S = malloc(sizeof(DynArrayStack));
if (!S) {
printf("Error: Could not create stack.\n");
return NULL;
}
S->capacity = 1;
S->top = -1;
S->array = malloc(S->capacity * sizeof(int));
if (!S->array) {
printf("Error: could not create stack.\n");
return NULL;
}
return S;
}
int isFullStack(DynArrayStack *S) {
return (S->top == S->capacity-1);
}
void DoubleStack(DynArrayStack *S) {
S->capacity *= 2;
S->array = realloc(S->array, S->capacity);
}
void Push(DynArrayStack *S, int data) {
if (isFullStack(S))
DoubleStack(S);
S->array[++S->top] = data;
}
int isEmptyStack(DynArrayStack *S) {
return S->top == -1;
}
int Top(DynArrayStack *S) {
if(isEmptyStack(S))
return INT_MIN;
return S->array[S->top];
}
int Pop(DynArrayStack *S) {
if (isEmptyStack(S)) {
printf("Array is empty. Returning INT_MIN.\n");
return INT_MIN;
}
return S->array[S->top--];
}
void DeleteStack(DynArrayStack *S) {
if (S) {
if (S->array)
free(S->array);
free(S);
printf("Stack deleted.\n");
}
}
edit: Actually it only does not error if I set two breakpoints, one before the while loop (so I step through it manually), and another before the DeleteStack() function. Still confused though.
There really isnt much I can say here.
Here is my lexer file:
#include <ctype.h>
#include <stdio.h>
#include "vector.h"
enum TokenType
{
tok_let = -1,
tok_iden = -2,
tok_int = -3,
tok_end = -4
};
typedef struct
{
int type;
char* str_d;
int int_d;
} Token;
char* seed;
int i=0;
char next_char()
{
i++;
return seed[i-1];
}
vector* get_tokens(char* in)
{
vector *toks;
vector_new(toks);
seed = in;
char tap;
if(isalpha(tap = next_char()))
{
char* iden_str="";
iden_str += tap;
char nc;
while(isalnum((nc = next_char())))
iden_str += nc;
if(iden_str == "let")
{
Token* tp;
tp->type = tok_let;
vector_push(toks, (void*)tp);
goto out;
}
Token* tp;
tp->type = tok_iden;
tp->str_d = iden_str;
vector_push(toks, (void*)tp);
}
out:
return toks;
}
int main()
{
vector* toks;
toks = get_tokens("let");
Token* ftok = (Token*)vector_get(toks, 0);
switch(ftok->type)
{
case tok_let:
printf("Its a let\n");
break;
default:
printf("Ummm lol nup\n");
break;
}
}
And here is my vector file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct d_vector
{
void **items;
int capacity;
int total;
} vector;
void vector_new(vector *v)
{
v->capacity = 4;
v->total = 0;
v->items = malloc(sizeof(void*)*v->capacity);
}
int vector_total(vector *v)
{
return v->total;
}
static void vector_resize(vector *v, int capacity)
{
void** items = realloc(v->items, sizeof(void*) * capacity);
if(items)
{
v->items = items;
v->capacity = capacity;
}
}
void vector_push(vector *v, void* item)
{
if(v->capacity == v->total)
vector_resize(v, v->capacity * 2);
v->items[v->total++] = item;
}
void vector_set(vector *v, int index, void* item)
{
if(index >= 0 && index < v->total)
v->items[index] = item;
}
void* vector_get(vector *v, int index)
{
if(index >= 0 && index < v->total)
return v->items[index];
return NULL;
}
void vector_remove(vector *v, int index)
{
if(index < 0 || index >= v->total)
return;
v->items[index] = NULL;
for (int i = 0; i < v->total - 1; i++) {
v->items[i] = v->items[i + 1];
v->items[i + 1] = NULL;
}
v->total--;
if (v->total > 0 && v->total == v->capacity / 4)
vector_resize(v, v->capacity / 2);
}
void vector_free(vector *v)
{
free(v->items);
}
When I run the code above, I get a Seg-Fault.
How can this be happening? Here is the output of gdb:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400656 in vector_new (v=0x1) at vector.h:14
14 v->capacity = 4;
As you can see, its segfaulting when i set the vector capacity!
But why?
It segfaults because you dereference a garbage pointer:
vector* get_tokens(char* in)
{
vector *toks;
vector_new(toks);
The variable toks is not assigned to anything meaningful, just whatever garbage value happens to be floating about. This gets passed into vector_new() which immediately dereferences it:
void vector_new(vector *v)
{
v->capacity = 4;
Then BAM! it blows up because v points nowhere appropriate.
Try mallocing a vector before making your call to vector_new() or put the malloc in vector_new() and have it return the pointer to the new vector instead. It's also a good idea to check the return value from malloc().
You might try something like:
vector *vector_new(void)
{
vector *v;
if ( (v = malloc(sizeof(*v))) == NULL ) {
/* Replace with something appropriate */
exit(EXIT_FAILURE);
}
v->capacity = 4;
v->total = 0;
if ( (v->items = malloc(sizeof(*v->items)*v->capacity)) == NULL ) {
/* Replace with something appropriate */
exit(EXIT_FAILURE);
}
return v;
}
Then change how you call it:
vector* get_tokens(char* in)
{
vector *toks;
toks = vector_new();
And for every malloc(), let there be a free(). Don't forget to clean up this allocation too or you'll leak memory:
void vector_free(vector *v)
{
free(v->items);
free(v);
}
(You defined a vector_free(), but never called it. You might want to consider doing that too.)
invalid pointer dereference happened
vector *toks;
vector_new(toks);
Should be
vector *toks = (vector*)malloc(sizeof(vector));
vector_new(toks);
I am having an error with the code we are using, was wondering if someone could help debug. Seems like we are getting a malloc error. Thanks.
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
int result = 0;
Word * current_pointer = malloc (sizeof(Word*));//creates a temporary variable for each pointer in the array
for (i=0; i<word_counter; i++) {
current_pointer = *(array+i); //accesses the current pointer
result = strcmp(norm_word, (current_pointer -> word)); //compares the string to each stored string
if (result == 0) {
found = true;
(current_pointer->freq)++;
break;
}
}
if(!found) {
if(pointer_counter == word_counter) {
array = realloc(array, sizeof(array)*2);
pointer_counter*=2;
}
Word * new_pointer = (Word*) malloc (sizeof(Word*));
strcpy(new_pointer -> word, norm_word);
*(array + (pointer_counter - 1)) = new_pointer;
word_counter++;
}
;
}
All pointers have the same size on your system. So a sizeof always returns the same size for any pointer. You want to allocate for the structure, so you need to use sizeof on the name without the star. malloc will return the pointer to that block of memory afterwards.
Here is a short implementation:
#include <iostream>
#include <string>
typedef struct
{
int num;
int numnum;
}numbers;
int main(int argc, char ** argv)
{
numbers* n = (numbers*)malloc(sizeof(numbers));
n->num = 1;
n->numnum = 2;
free(n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAXSIZE 64
typedef struct word {
char word[MAXSIZE];
int freq;
} Word;
int word_counter = 0;
size_t pointer_counter = 16;//Number of pointers that ensure
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
Word *current_pointer = *array;
for (i=0; i<word_counter; i++) {
if(strcmp(norm_word, current_pointer->word) == 0){
found = true;
current_pointer->freq++;
break;
}
++current_pointer;
}
if(!found) {
if(pointer_counter == word_counter) {
pointer_counter *= 2;
*array = realloc(*array, sizeof(Word)*pointer_counter);
}
Word *new_pointer = *array + word_counter;
new_pointer->freq = 1;
strcpy(new_pointer->word, norm_word);
++word_counter;
}
}
int main(void){
Word *vocabulary = calloc(pointer_counter, sizeof(Word));
char norm_word[MAXSIZE];
while(1==scanf("%s", norm_word)){
readWords(norm_word, &vocabulary);
}
{
int i;
for(i = 0; i < word_counter; ++i){
printf("%s(%d)\n", vocabulary[i].word, vocabulary[i].freq);
}
}
free(vocabulary);
return 0;
}
Everything seems to work fine while dynamically creating the array
but core dumped while trying to print it backwards.
It managed to print only the last string and then segmentation fault.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
void init_array(void ***pt, int *ptlen) {
*pt=NULL;
*ptlen=0;
}
void trim_array(void ***pt, int *ptlen, int len) {
*pt=(void**)realloc(*pt, len*sizeof(void*));
*ptlen=len;
}
void write_array(void ***pt, int *ptlen, int pos, void *v) {
if (pos >= *ptlen)
trim_array(pt, ptlen, pos+1);
*pt[pos]=v;
}
void *read_array(void ***pt, int *ptlen, int pos) {
return(*pt[pos]);
}
void destroy_array(void ***pt, int *ptlen) {
trim_array(pt, ptlen, 0);
*pt=NULL;
}
int main(int argc, char *argv[]) {
void **t;
int tlen;
void ***pt = &t;
int *ptlen = &tlen;
char s[256],*p; int i;
init_array(pt, ptlen);
i = 0;
do {
printf("give name:\n");
scanf("%255s",s);
write_array(pt, ptlen, i, (void*)strdup(s));
i++;
} while (strcmp(s,"end"));
for (--i; i>=0; i--) {
p = (char*)read_array(pt, ptlen, i);
printf("%s\n",p);
free(p);
}
destroy_array(pt, ptlen);
return(0);
}
The [] operator has a higher precedence than the * operator. You need to change:
*pt[pos]
to:
(*pt)[pos]
in both places where it occurs.
This error is a direct result of writing almost deliberately confusing code with runaway indirection. You'd save yourself a lot of trouble and make things much easier if you wrapped a lot of this stuff in a struct and created some proper interface functions for it.
Something like this would be a bit better form (although "array" is not really a great name for this data structure):
main.c:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "array.h"
#define MAX_BUFFER_LEN 255
int main(void) {
Array myarray = array_init(10, true);
/* Loop for input until user enters "end" */
char buffer[MAX_BUFFER_LEN];
while ( true ) {
printf("Give name: ");
fflush(stdout);
/* Get input and remove trailing '\n' if necessary */
fgets(buffer, MAX_BUFFER_LEN, stdin);
size_t last = strlen(buffer) - 1;
if ( buffer[last] == '\n' ) {
buffer[last] = '\0';
}
/* Terminate loop on "end" without adding to array... */
if ( !strcmp(buffer, "end") ) {
break;
}
/* ...or append input to array and continue loop */
array_append(myarray, strdup(buffer));
};
/* Output contents of array */
size_t n = array_size(myarray);
for ( size_t i = 0; i < n; ++i ) {
char * data = array_getdata(myarray, i);
printf("%zu: %s\n", i + 1, data);
}
/* Clean up and exit */
array_destroy(myarray);
return EXIT_SUCCESS;
}
array.h:
#ifndef ARRAY_TYPE_H
#define ARRAY_TYPE_H
#include <stdbool.h>
typedef struct array_type * Array; /* Opaque type for user */
Array array_init(const size_t capacity, const bool free_on_delete);
void array_append(Array array, void * data);
size_t array_size(const Array array);
void * array_getdata(Array array, const size_t index);
void array_deletetop(Array array);
void array_destroy(Array array);
#endif /* ARRAY_TYPE_H */
array.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "array.h"
/* Struct definition is visible only to implementation */
struct array_type {
void ** elements;
size_t capacity;
size_t top;
bool free_on_delete;
};
/* Static functions used by the implementation */
static bool array_isfull(Array array) {
return (array->top + 1) == array->capacity;
}
static void array_resize(Array array, const size_t new_capacity) {
array->capacity = new_capacity;
array->elements = realloc(array->elements,
array->capacity * sizeof (*array->elements));
if ( array->elements == NULL ) {
fputs("Error allocating memory.", stderr);
exit(EXIT_FAILURE);
}
}
/* Interface functions */
Array array_init(const size_t capacity, const bool free_on_delete) {
struct array_type * new_array = malloc(sizeof *new_array);
if ( new_array == NULL ) {
fputs("Error allocating memory.", stderr);
exit(EXIT_FAILURE);
}
new_array->elements = malloc(capacity * sizeof (*new_array->elements));
if ( new_array->elements == NULL ) {
fputs("Error allocating memory.", stderr);
exit(EXIT_FAILURE);
}
new_array->capacity = capacity;
new_array->top = 0;
new_array->free_on_delete = free_on_delete;
return new_array;
}
void array_append(Array array, void * data) {
if ( array_isfull(array) ) {
array_resize(array, array->capacity * 2);
}
array->elements[array->top++] = data;
}
size_t array_size(const Array array) {
return array->top;
}
void * array_getdata(Array array, const size_t index) {
return array->elements[index];
}
void array_deletetop(Array array) {
if ( array->free_on_delete ) {
free(array->elements[array->top - 1]);
}
array->elements[--array->top] = NULL;
}
void array_destroy(Array array) {
while ( array->top > 0 ) {
array_deletetop(array);
}
free(array->elements);
free(array);
}
Sample output:
paul#local:~/src/c/scratch/array$ ./array
Give name: Dave Dee
Give name: Dozy
Give name: Beaky
Give name: Mick
Give name: Titch
Give name: end
1: Dave Dee
2: Dozy
3: Beaky
4: Mick
5: Titch
paul#local:~/src/c/scratch/array$
I'm trying to store strings into dynamical allocated memory. I'm able to break the strings down and store them within the members of the struct and print them perfectly within the function readFile, but when it comes to printing it in main, it's only printing the last scan and everything else is null. I'm thinking that maybe I'm not allocating the array of structures correctly. Here's my program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _MSC_VER
#include <crtdbg.h> // needed to check for memory leaks (Windows only!)
#endif
#define MEM_ERROR printf("Not enough memory\n")
#define FLUSH while( getchar() != '\n' )
typedef struct
{
char id[5];
char *name;
int *sales;
int total;
int low;
int high;
}PERSON;
typedef struct
{
int worker;
int weeks;
PERSON *pAry;
}HEADER;
// Function Declaration
void valiFile(char nameIn[]);
FILE* openFile(char nameIn[]);
void getHeader(FILE* fpFile, HEADER *pHead);
PERSON* aloPerson(int workers);
void readFile(FILE* fpFile, HEADER *pHead);
char* aloName(HEADER *pHead, int strCount);
void repeat(char nameIn[]);
int main ( void )
{
// Local Declaration
FILE* fpFile;
char nameIn[25];
char *endPro = "end";
HEADER *pHead = (HEADER*)calloc(1, sizeof(HEADER));
// Statement
printf("Please select file to to open.\nsales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
do
{
valiFile(nameIn);
fpFile = openFile(nameIn);
getHeader(fpFile, pHead);
readFile(fpFile, pHead);
//printf("%s\n", pHead->pAry[0].id);
//free(pHead);
repeat(nameIn);
}
return 0;
}// main
/* ========== valiFile ==========
========== */
void valiFile(char nameIn[])
{
// Local Declaration
char *file = "sales";
char *file2 = "sales_2";
int i;
int check = 0;
// Statement
do
{
for(i = 0; nameIn[i]; i++)
{
nameIn[i] = tolower(nameIn[i]);
}
if(strcmp(file, nameIn) != 0)
{
if(strcmp(file2, nameIn) != 0)
{
printf("\nPlease enter a valid file.\n");
printf("sales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
}
else
check = 1;
}
else
check = 1;
}
while(check != 1)
;
return;
}// valiFile
/* ========== openFile ==========
========== */
FILE* openFile(char nameIn[])
{
// Local Declaration
FILE* fpFile;
char *strSale = "sales";
// Statement
if(strcmp(strSale, nameIn) == 0)
{
fpFile = fopen("sales.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
else
{
fpFile = fopen("sales_2.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
return fpFile;
}// openFile
/* ========================= getHeader ========================
============================================================*/
void getHeader(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
int worker, salesWeek, i;
PERSON *list;
// Statement
fscanf(fpFile, "%d %d", &worker, &salesWeek);
list = aloPerson(worker);
HEADER header = {worker, salesWeek, list};
*pHead = header;
return;
}// getHeader
/* aloPerson
*/
PERSON* aloPerson(int worker)
{
// Local Declaration
PERSON *list;
// Statement
list =(PERSON*)calloc(worker, sizeof(PERSON));
if(list == NULL)
{
MEM_ERROR, exit(103);
}
return list;
}// aloPerson
/* readFile
*/
void readFile(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
char temp[50];
int strCount = 0;
char *loc;
char *ptr;
int i;
// Statement
fscanf(fpFile, "%*d %*d");
for(i = 0; i < pHead->worker; i++)
{
while(fgets(temp, sizeof(temp), fpFile))
{
ptr = temp;
loc = strchr(temp, ' ');
strncpy(pHead->pAry[i].id, temp, (loc - ptr));
ptr += (loc - temp);
*ptr++;
loc = strchr(temp, ';');
strCount = (loc - ptr);
pHead->pAry[i].name = aloName(pHead, strCount);
strncpy(pHead->pAry[i].name, ptr, (loc - ptr));
ptr += (loc - ptr);
printf("%s\n", pHead->pAry[i].name);
}
}
return;
}// readFile
/* aloName
*/
char* aloName(HEADER *pHead, int strCount)
{
// Local Declaration
char *names;
// Statement;
names = malloc((strCount + 1)*sizeof(char));
return names;
}