I'm having a problem that must be idiot, but I can't see why.
the main code reaches the "2test" print and then stops responding at l->n = 0;
This is my first (real) program in C, so my knowledge is small in this language.
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "list.h"
int main(){
TList* l;
FILE* txt = fopen("arqtxt.txt", "r");
char aux[80];
int c = fgetc(txt), x = 0;
printf("1test");
TList_Init(l);
printf("6test");
while ((c = fgetc(txt)) != EOF){
printf("%d",c);
while (!(isalpha(c))) c = fgetc(txt);
if (isupper(c)) c = c+32;
if (islower(c)) aux[x++] = (char) c;
else{
TList_Insert(l, aux);
strcpy(aux, "");
}
}
TList_Print(l);
getchar();
return 0;
}
list.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
void TList_Init (TList* l){
printf("2test");
l->n = 0;
printf("3test");
l->tam = 100;
printf("4test");
l->v = malloc(sizeof(TItem)*l->tam);
printf("5test");
}int TList_Search (TList* l, char* c){
int i;
for (i = l->n-1; i >= 0; i--)
if (strcmp(l->v[i].chave, c) == 0) return i;
return -1;
}
void InsertSort (TItem* v, int n){
int i,j;
TItem aux;
for (i = 1; i < n; i++){
aux = v[i];
j = i-1;
while (j >= 0 && strcmp(aux.chave, v[j].chave) < 0){
v[j+1] = v[j];
j--;
}
v[j+1] = aux;
}
}
void TList_Insert (TList* l, char word[80]){
if (l->n == l->tam){
l->tam += 100;
l->v = realloc(l->v, sizeof(TItem)*l->tam);
}
char* c = malloc(sizeof(char)*strlen(word));
c = word;
int aux = TList_Search(l, c);
if (aux != -1){
l->v[aux].no++;
return;
}
l->v[l->n].chave = c;
l->v[l->n].no = 1;
l->n++;
InsertSort(l->v, l->n);
}
void TList_Print (TList* l){
int x;
for (x = 0; x <= l->n; x++)
printf("%s - %d", l->v[x].chave, l->v[x].no);
}
list.h:
#ifndef LIST_H_
#define LIST_H_
typedef struct Item{
char* chave;
int no;
} TItem;
typedef struct List{
TItem* v;
int n, tam;
} TList;
void TList_Init (TList*);
void TList_Insert (TList*, char[]);
void TList_Print (TList*);
#endif
output:
||=== Build: Debug in EP1 (compiler: GNU GCC Compiler) ===|
C:\Users\Lucas\Desktop\EP1\main.c||In function 'main':|
C:\Users\Lucas\Desktop\EP1\main.c|13|warning: 'l' is used uninitialized in this function [-Wuninitialized]|
||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
||=== Run: Debug in EP1 (compiler: GNU GCC Compiler) ===|
-------------- Run: Debug in EP1 (compiler: GNU GCC Compiler)---------------
Checking for existence: C:\Users\Lucas\Desktop\EP1\bin\Debug\EP1.exe
Executing: "C:\Program Files (x86)\CodeBlocks/cb_console_runner.exe" "C:\Users\Lucas\Desktop\EP1\bin\Debug\EP1.exe" (in C:\Users\Lucas\Desktop\EP1\.)
Process terminated with status -1073741510 (0 minute(s), 9 second(s))
To expand on Jens' correct answer: TList* l; initialises a pointer to an address in memory - it does not allocate the memory for TList itself, so l most likely points to some random chunk of memory that you should not have access to.
You'd have to either call
l = malloc(sizeof(*l))
to reserve memory. Remember to call free(l); once you're done.
Alternatively declare l not as pointer, but rather as TList:
TList l;
[...]
TList_Init(&l);
This reserves memory in stack for TList, and passes a pointer via & to the method, with the proper memory allocated - in this case, you do not need to free the memory, as it's automagically freed once the method in which the variable was declared returns.
You never initialize the pointer l before you pass it to TList_Init(l);. Then assigning to l->n leads to undefined behavior in C language standardese because you use an indeterminate value.
What about making TList_Init() returning a ptr-to-TList instead?
TList *TList_Init (void)
{
TList *l;
l = malloc (sizeof *l);
/* Check l != NULL here ... omitted. */
printf("2test\n");
l->n = 0;
printf("3test\n");
l->tam = 100;
printf("4test\n");
l->v = malloc(sizeof(TItem) * l->tam);
printf("5test\n");
return l;
}
Related
I was working on pop and push methods on the stack. Actually in this code I am creating dynamic array using pointers and malloc function. Then I was trying to add or delete elements to dynamic array with pop and push methods.But I getting the error in the question. I can't see any error in the code. Can you help me?
Here my main.c file
#include <stdio.h>
#include <stdlib.h>
#include "main_header.h"
stack * init(){
stack *s = (stack *) malloc(sizeof(stack));
s->items = NULL;
s->top = 0;
s->count = 2;
return s;
}
int pop(stack *s){
if(s->items == NULL){
printf("Items is empty.\n");
return -1;
}
if(s->top<=s->count/4){
int *items2 = (int *)malloc(sizeof(int)*s->count/2);
for (int i = 0; i < (s->count/2); i++){
items2[i] = s->items[i];
}
free(s->items); // burada "dizi" adındaki dizimiz dizi2 ile aynı yeri gösterdiğinde önceki 2 elemanlık dizi lost in space olacak bunu önlemek için free(dizi) diyerek o 2 elemanı bellekten siliyoruz.
s->items = items2;
s->count /= 2;
}
return s->items[--s->top];
}
void push(int a, stack *s){
if(s->items == NULL){
s->items = (int *)malloc(sizeof(int) * 2);
}
if(s->top>=s->count){
int *items2 = (int *)malloc(sizeof(int)*s->count*2);
for (int i = 0; i < s->count; i++)
items2[i] = s->items[i];
free(s->items); // burada "dizi" adındaki dizimiz dizi2 ile aynı yeri gösterdiğinde önceki 2 elemanlık dizi lost in space olacak bunu önlemek için free(dizi) diyerek o 2 elemanı bellekten siliyoruz.
s->items = items2;
s->count *= 2;
}
s->items[s->top++] = a;
}
void getItems(stack *s){
printf("count: %d\n", s->count);
for (int i = 0; i < s->top; i++) {
printf("%d\n", s->items[i]);
}
}
main_header.h file
#ifndef main
#define main
struct s {
int count;
int top;
int *items;
};
typedef struct s stack;
stack * init(void);
int pop(stack *);
void getItems(stack *);
void push(int, stack *);
#endif
test_stack.c file
#include <stdio.h>
#include <stdlib.h>
#include "main_header.h"
int main(){
stack *s1 = init();
stack *s2 = init();
for (int i = 0; i < 10; i++) {
push(i*10, s1);
}
getItems(s1);
for (int i = 0; i < 10; i++) {
push(pop(s1), s2);
}
return 0;
}
After #define main in “main_header.h”, the code int main(){ in “test_stack.c” is replaced by int (){. This causes the syntax error that the compiler (not Xcode) reports.
Do not use main in “main_header.h” as an indicator for whether the header file has been included already. Use some other name that you will not use for anything else, such as main_h or main_header_h.
(Clang is the compiler. Xcode is the overall integrated development environment that facilitates use of the compiler, organizes your projects files, opens editors, maintains your project options, and so on.)
I am writing a HW for school, where I should implement a circular buffer and I ran into 2 things. VS Code says that:
too few arguments in function call [8,21]
expected a ';' [9,5]
But I'am quite sure, I have not made any mistake so far. I also don't know how to compile it, GCC won't take that. Makefile provided by school throws some error, but none regarding this issue.
I've got C/C++ extension form Microsoft [v1.2.2]. Are errors/problems handled by that one?
Here is the code queue.c:
#include "queue.h"
// TODO - your code
queue_t* create_queue(int capacity){
queue_t * q;
q->capacity = capacity;
q->count = 0;
q->arr = malloc(capacity*sizeof(int));
if(q->arr == NULL){
fprintf(stderr, "ERROR: cannot alocate enough memory!\n"); // here is the er#1
}
q->arr_end =(int*)q->arr + capacity * sizeof(int);
return q; // er#2 occurs here
}
And here queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* Queue structure which holds all necessary data */
typedef struct {
// TODO - Include your data structure here
int capacity; // the max # of elemetns, that can be stored
int count; // # of elements in Q
int * arr; // the array itself
int * arr_end; // pointer to the end of arr (ie: *(arr+int*len))
int * read; // position to read from; ie: HEAD
int * write; // position to write form; ie: TAIL
} queue_t;
/* creates a new queue with a given size */
queue_t* create_queue(int capacity);
// ...
#endif /* __QUEUE_H__ */
Output of the GCC for gcc queue.c
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
And this is the main.c as is from school:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "queue.h"
/* allocate new integer with value a and add it to the queue */
void add(int a, queue_t *queue)
{
int *p = (int*)malloc(sizeof(int));
*p = a;
bool ret = push_to_queue(queue, (void*)p);
if (!ret) {
// free memory on failure
free(p);
}
}
/* print the int value on pointer p */
void print_int(void *p)
{
if (p != NULL) {
printf("%d\n", *((int*)p));
} else {
printf("NULL\n");
}
}
/* pop from the queue, print and free the element */
void pop(queue_t *queue)
{
void *p = pop_from_queue(queue);
print_int(p);
free(p);
}
/* get i-th element and print it (do not remove them) */
void get(int idx, queue_t *queue)
{
print_int(get_from_queue(queue, idx));
}
/*
* TEST PROGRAM
* - reads commands from stdin and executes them in the queue
*/
int main(int argc, char *argv[])
{
int n;
/* the tested queue */
queue_t *queue;
// read the size of the queue
scanf("%d", &n);
// create queue
queue = create_queue(n);
while (true) {
char s[2];
// read one command
int ret = scanf("%1s", s);
if (ret != 1) {
break;
}
// add command
if (s[0] == 'a') {
int a;
// read the argument of the command
ret = scanf("%d", &a);
if (ret != 1) {
break;
}
add(a, queue);
// remove command
} else if (s[0] == 'r') {
pop(queue);
// get command
} else if (s[0] == 'g') {
int a;
// read the argument of the command
ret = scanf("%d", &a);
if (ret != 1) {
break;
}
get(a, queue);
}
}
// remove rest of the elements in the queue
while (get_queue_size(queue)) {
void *p = pop_from_queue(queue);
free(p);
}
// free memory
delete_queue(queue);
queue = NULL;
// return 0 on succes
return 0;
}
You forget to reserve space for the queue:
queue_t * q = malloc(sizeof *q);
if (q != NULL)
{
q->capacity = capacity;
...
Also
q->arr_end =(int*)q->arr + capacity * sizeof(int);
here you want (assuming that you want a pointer to the last element):
q->arr_end = q->arr + capacity - 1;
pointer arithmetic is done in terms of elements (not bytes)
Regarding your compile error, it seems that you forget to include the unit containing main, try with
gcc main.c queue.c
So I was originally writing my code in code blocks but when I'd try to compile it would always give me errors saying that it wasn't understanding the references i was making to functions in other files.At which point I starting using atom, but it's come to the point where I need to use he debugging tool in code blocks and I'm still getting the same errors even though my code compiles when I run it through gcc. Can someone help please?? These are the errors I'm getting.
||=== Build: Debug in A2 (compiler: GNU GCC Compiler) ===|
obj\Debug\main.o||In function main':|
main.c|18|undefined reference tocreateMyVector'|
main.c|29|undefined reference to PathInit'|
main.c|30|undefined reference toAllPathsRec'|
main.c|31|undefined reference to `PathPrint'|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
#include "path.h"
#define BUFFERSIZE 20
int main()
{
Vector *leVector;
unsigned int size;
char leArray[BUFFERSIZE];
scanf("%u\n",&size);
fgets(leArray,sizeof(leArray),stdin);
leVector = createMyVector(size);
char *element = strtok(leArray, " ");
int i;
for(i=0;i<size;i++){
*(leVector->item + i) = atoi(element);
element = strtok(NULL," ");
}
Path Solution;
PathInit(&Solution,size);
AllPathsRec(0,leVector,&Solution);
PathPrint(&Solution);
return 0;
}
vector.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
void vectorRead(Vector * V){
printf("Size of the array is: %d\n",V->size);
int i;
for(i = 0; i < V->size; i++){
if(i == V->size)
printf("%d\n ",*(V->item+i));
else
printf("%d ",*(V->item+i));
}
}
Vector * createMyVector(int size){
Vector * vect = (Vector *)malloc(sizeof(Vector));
vect->size = size;
vect->item = (int *)malloc(sizeof(int)*size);
return vect;
}
path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
#include "path.h"
void PathInit(Path *P, int vsize){
P->size = vsize;
P->item = (int *)malloc(sizeof(int)*vsize);
P->top = -1;
}
int AllPathsRec(int position, Vector *V, Path *Solution){
PathAddEntry(Solution,position);
position += *(V->item + position);
while(Solution->top != V->size -1){
AllPathsRec(position, V, Solution);
}
return 0;
}
int PathAddEntry(Path *P, int entry){
if(P->top >= P->size - 1){
printf("ERROR: STACK OVERFLOW\n");
return 1;
}
P->top++;
*(P->item + P->top) = entry;
return 0;
}
int PathRemoveEntry(Path *P){
if(P->top <= -1){
printf("\nERROR: NO ELEMENT TO REMOVE\n");
return 1;
}
P->top--;
return 0;
}
void PathPrint(Path *P){
printf("Size of the Solution array is: %d\n",P->size);
int i;
for(i = 0;i <= P->top; i++){
if(i == P->top)
printf("%d\n ", *(P->item+i));
else
printf("%d ", *(P->item+i));
}
}
vector.h
#ifndef VECTOR_H
#define VECTOR_H
typedef struct {
int size;
int *item;
}Vector;
Vector * createMyVector(int size);
void vectorRead(Vector * V);
#endif
path.h
#ifndef PATH_H
#define PATH_H
typedef struct{
int size;
int top;
int *item;
}Path;
void PathInit(Path *P, int size);
int AllPathsRec(int position, Vector *V, Path *Solution);
int PathAddEntry(Path *P, int entry);
int PathRemoveEntry(Path *P);
void PathPrint(Path *P);
#endif
I wonder if I'm doing something wrong in my program.
I manage to create a HashTable but when I send it through parameter to my displayingList() function, it crashes.
source.c (contains my functions):
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include "header.h"
#define MAX 255
int countLetters(char myStr[])
{
int myLen = strlen(myStr), i;
int wordLen = 0;
for (i = 0 ; i < myLen; ++i)
{
wordLen += (int)(myStr[i]);
}
return (wordLen%256);
}
void populateList(NodeT *T[255], char myStr[])
{
NodeT *p, *q;
p = (NodeT *)malloc(sizeof(NodeT));
strcpy (p->key, myStr);
int myPos = countLetters(myStr);
if(T[myPos] == NULL)
{
p->next = NULL;
T[myPos] = p;
}
else
{
q = T[myPos];
p->next = q;
T[myPos] = p;
}
}
void displayList(NodeT *T[255])
{
int i;
NodeT *p;
for(i = 0 ; i < 255; ++i)
{
if(T[i] != NULL)
{
printf("Index: %d - Data:", i);
p = T[i];
while(p != 0)
{
printf("%s, ", p->key); // HERE IT CRASHES.
p = p->next;
}
printf("\n");
}
}
}
main.c (contains the int main()):
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(void)
{
NodeT *T[255];
int n, i;
printf("Give no. of elements:");
scanf("%d", &n);
fflush(stdin);
for(i = 0 ; i < n ; ++i)
{
char name[100];
gets(name);
populateList(T, name);
}
displayList(T);
return 0;
}
header.h (and my header):
#ifndef HEADER_H
#define HEADER_H
typedef struct cell
{
char key[100];
struct cell *next;
}NodeT;
int countLetters(char myStr[]);
void populateList(NodeT *T[], char myStr[]);
void displayList(NodeT *T[]);
#endif // HEADER_H
I tried to see what exactly happens with debugger and it seems that when I send T[] list to displayList() function, actually it doesn't have the same structure as it has in main.c.
ISSUE: the insertion works fine, but when I try to display my list (on each index) it crashes.
Any ideas?
Thanks in advance.
The possible solution is to declare the NodeT *T[255] global. However it isn't the best practice at all.
I'm working on a Priority queue with an array implementation. Everything seems to work fine but I get this error: conflicting types for 'remove'
I've declared the function in its header file, I've included the header file but the compiler stil complains. I think the problem resides somewhere else.
Here is pqueue.h:
#ifndef PQUEUE_H
#define PQUEUE_H
//---------------
#define HIGHP 0
#define MEDP 1
#define LOWP 2
#define MAXEL 10
#include <stddef.h>
typedef struct message {
char data[100];
int priority;
} message;
typedef struct pQueue {
struct message messages[10];
int rear;
int front;
int size;
} pQueue;
void initPQueue(pQueue *pq);
void add(pQueue *pq, char *data, int pri);
char* remove(struct pQueue *pq); // Error: conflicting types for: 'remove'
int isEmpty(pQueue *pq);
#endif
pqueue.c:
#include "pqueue.h"
#include <string.h>
void initPQueue(pQueue *pq) {
pq->front = 0;
pq->rear = 0;
pq->size = 0;
}
void add(pQueue *pq, char *data, int pri) {
if (pq->size > MAXEL) {
return; // NOTE: data is lost
}
message m;
strcpy(m.data, data);
m.priority = pri;
if (isEmpty(pq)) {
pq->messages[pq->rear] = m;
pq->rear = (pq->rear % (MAXEL - 1)) + 1;
return; // done
}
/**TODO: NEEDS REPAIR**/
int i = 0;
int j = 0;
for (; i < pq->rear; i = (i % (MAXEL - 1)) + 1) {
if (m.priority > pq->messages[i].priority) {
// found element with higher or equal priority
for (j = pq->rear - 1; j >= i; j = (j % (MAXEL - 1)) - 1) {
pq->messages[j] = pq->messages[j - 1];
}
break;
}
}
pq->messages[i] = m;
/****/
pq->size++;
}
char* remove(struct pQueue *pq) {
if (isEmpty(pq)) {
return NULL ;
}
pq->size--;
return pq->messages[pq->front].data;
}
int isEmpty(pQueue *pq) {
if (!pq->size)
return 1;
return 0;
}
Any thoughts?
int remove(const char *path) is a standard function. You need to choose a different name for yours.
To echo what everyone else has said, there is a standard function. But to add to this, in C, you should always prefix your functions with the name of your library and of the type that it operates on to avoid these sorts of issues. For example, it would be better to name your function something like:
mylibrary_pqueue_remove
This would avoid naming clashes with the standard library and with other peoples' code.
remove is a reserved identifier, you can't use it in your program, as long as you include <stdio.h>.
7.21.4.1 The remove function
#include <stdio.h>
int remove(const char *filename);
The remove function causes the file whose name is the string pointed to by
filename to be no longer accessible by that name. A subsequent attempt
to open that file using that name will fail, unless it is created
anew. If the file is open, the behavior of the remove function is
implementation-defined.