is it possible to do say
int filename = 0;
typedef struct{
char name;
char sname;
int number;
}foo;
foo filename;
filename++;
foo filename;
and have a new foo struct named 1 and another named 2?
C isn't interpreted language, so you can't create variable names runtime. The other way is to create array having multiple instances.
typedef struct{
char name;
char sname;
int number;
}foo;
foo *files = malloc(sizeof(foo)*3);
files[0].name = "A";
files[1].name = "B";
files[2].name = "C";
Edit: used malloc instad new foo[3]
No, this is not possible. Declaring foo filename; will attempt to declare another variable named filename of type foo, so the integer value will never come into play there.
In addition, the introduction of two more variables named filename within the same scope wouldn't be allowed.
You probably want a linked list, rather than an array, if you will be changing its size often. Then, your code looks something like:
typedef struct node{
char name;
char sname;
int number;
struct node* next;
}foo;
And you would use functions like the following to add new nodes/fetch nodes:
foo head = NULL;
void addNode(foo newNode)
{
if(head == NULL)
head = newNode;
else
{
foo temp = head;
while(foo->next != NULL)
foo = foo->next;
foo->next = newNode
}
}
foo fetchNode(int index)
{
if(index < 0)
return NULL;
int n = 0
foo temp = head;
while(n < index && temp != NULL)
{
temp = temp->next;
n++;
}
return temp;
}
The way this works is that each node has the necessary data, plus a pointer to the next node, which is NULL if its the last node. Then, all you need is a pointer to the first one and you can fetch nodes by walking the next pointers. This also makes it trivial to delete a node that is partway down the list.
Related
Basically I have a struct with several members, named a-z. I have a string where I want each letter to correspond to the correct struct member. Currently I use a switch statement with each case in order to access the correct letter member of the struct, but Im wondering if theres a better (cleaner/shorter code) way to do this, without having to put 26 case statements with nearly identical code inside? My code looks somewhat like this:
typedef struct node
{
struct node *a;
struct node *b;
struct node *c;
...
struct node *z;
}node;
node *nTable[26][26][27];
int main
{
...
node *nWord = malloc(sizeof(node));
node *nPath = nWord;
nTable[0][0][0] = nWord;
char *cWord
cWord = "abcde";
for (int n = 0; n < 5; n++)
{
nWord = malloc(sizeof(node));
switch (cWord[n])
case 'a':
nPath->a = nWord;
nPath = nWord;
break;
case 'b':
nPath->b = nWord;
nPath = nWord;
...
case 'z':
nPath->z = nWord; //code is the same for each case, only difference between each is which member its assigned to
nPath = nWord;
}
}
Note the above code is a much reduced form of my actual code, so there may be some basic syntax and other errors within this example, but the general purpose of my code should be apparent.
So is there a cleaner way to do this, without using a case statement for each letter? Something simple like "nPath->cWord[n] = code;" would be perfect! (though this as it is, obviously does not work)
Any ideas would be great! Also sorry in advance if Ive left out any important info
For starters this construction
char *cWord = {a,b,c,d,e};
is syntactically invalid. You may not initialize a scalar object with a braced list with more than one initializer.
As for you question when you could declare one data member of an array type within the structure instead of numerous data members like
struct node *a;
For example
#define N 26
typedef struct node
{
struct node *nodes[N];
} node;
And then use the following approach
const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *p = strchr( letters, toupper( ( unsigned char )cWord[i] ) );
if ( p != NULL )
{
nPath->nodes[p - letters] = data;
// or
// nPath->nodes[p - letters] = malloc( sizeof( node ) );
}
Maybe you can focus on the words: at first you have a linked list of words. And then there will be a linked list for every letter in order do build an array of linked lists of words.
Consider this example:
#include <stdio.h>
typedef struct _node
{
char* word;
struct _node* next;
struct _node* prev;
}; // single node contains one word
typedef struct _node Node;
typedef struct
{
char letter;
unsigned size;
unsigned limit;
Node* start;
Node* end;
} _list;
typedef _list Data;
In this way you have a bit more of structure
See this code
#include "x25list.h"
int main(int argc, char** argv)
{
Data* db[26];
for (int i = 'a'; i < 'z'; i += 1)
{ // builds initial linked lists
int ix = i - 'a';
db[ix] = (Data*)malloc(sizeof(Data));
db[ix]->letter = i;
db[ix]->size = 0;
db[ix]->end = NULL;
db[ix]->start = NULL;
}; // for()
return 0;
};
In this way you have a linked list for each letter already built and start to catalog words using the notes on the lists pointed by the value of the letter minus the value of 'a'.
I would like to set root_1's name to be "hi", just like the output of the current output of this code, which is mentioned below. Unfortunately, it doesn't work.
struct Node
{
int num;
char *name;
struct Node *child;
struct Node *sibling;
};
int main()
{
struct Node root = {1,"hi",NULL,NULL};
struct Node *root_0 = &root;
struct Node **root_1 = &root_0;
char *s = root.name; //s is now hi
root_0 -> name = s;
//*root_1 -> name = s; //?????
printf("%s\n", root_0 -> name);
return 0;
}
That's not how pointers work. root_1 doesn't have a name or any other field - all it does is pointing to root. You don't have to set anything for root_0 and root_1, you can access root's name through them like this:
int main()
{
struct Node root = { 1,"hi",NULL,NULL };
struct Node *root_0 = &root;
struct Node **root_1 = &root_0;
printf("root_0: %s\n", root_0->name);
printf("root_1: %s\n", (*root_1)->name);
return 0;
}
This prints:
root_0: hi
root_1: hi
So in other words, (*root_1)->name is root_0->name, which is root.name. Perhaps it's less confusing if you consider that root_0->name is the same as writing (*root_0).name and (*root_1)->name is like writing (**root_1).name. You just add a * per pointer level.
It's just that * has a lower priority than ->.
*foo->bar = *(foo->bar) != (*foo)->bar.
So in your case you'd need (*root_1)->name = s;
I have a struct:
struct person{
char* name;
char* surname;
int age;
};
And I use this struct inside another struct for linked list:
struct listNode {
struct person data;
struct listNode *nextPtr;
};
typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;
I am trying to insert one struct into the linked list. After that I want to get this struct by index and change the age value. In main, I have these codes:
int main() {
ListNodePtr startPtr = NULL;
struct person p;
p.age = 22;
p.surname = "Pilkington";
p.name = "Anthony";
insert(&startPtr, p);
printf("Age1:%d\n", p.age);
struct person p2 = getStruct(&startPtr, 0);
p2.age++;
printf("Age2:%d\n", p2.age);
struct person p3 = getStruct(&startPtr, 0);
printf("Age3:%d\n", p3.age);
return 0;
}
Now, my insert function and getStruct function are working correctly. But I cannot increment the age value. My output is:
Age1:22
Age2:23
Age3:22
I want to make the Age3 23. In insert function, I already allocate memory with malloc, but why can't I change the first value? How can I change this value without removing/adding the node from list?
I search the subject but I cannot find the answer that I want. So, If you can help me I appreciate that.
---EDIT-----
Sorry for not posting getStruct method, I am adding it below:
struct person getStruct(ListNodePtr *sPtr, int index) {
ListNodePtr currentPtr;
struct person c;
int counter = 0;
currentPtr = *sPtr;
while (currentPtr != NULL) {
if (counter == index) {
c = currentPtr->data;
}
counter++;
currentPtr = currentPtr->nextPtr;
}
return c;
}
Here:
struct person p2 = getStruct(&startPtr, 0);
You return a person by value, which is to say you make a copy. Then you modify the copy, not the original. You'll need to do this instead:
struct person *p2 = getStruct(&startPtr, 0);
p2->age++;
printf("Age2:%d\n", p2->age);
That is, return a pointer, which you can use to modify what it points to. This also requires a slight change to getStruct(), whose code you haven't posted.
I have a struct and in that a struct i have a character pointer but and i am creating different instances of this struct but when i am changing the pointer in one struct the other is also changing.
#include <stdio.h>
#include <stdlib.h>
typedef struct human{
int age;
char name[100];
} Human;
int main(){
FILE *s = fopen("h.txt","r");
if(s==NULL){
printf("file not available");
}
for(int i=0 ;i<5;i++){
Human h;
fscanf(s,"%d",&h.age);
fscanf(s,"%s",h.name);
insertintolinkedlist(h);
// this method is going to insert the human into the linked list
}
return 0;
}
what is happening that all humans in the linked list have different ages but same name!
You need to allocate memory to hold the name.
char* name is just a pointer - it has no memory for saving the name.
You change it to
char name[100];
Remember to check that the names you put into Human.name isn't longer than 100 characters.
To use a linked list you can do something like:
typedef struct human{
int age;
char name[100];
struct human* next;
} Human;
int main()
{
Human* head = NULL;
Human* tail = NULL;
for(.....)
{
Human* h = malloc(sizeof(Human));
if (head == NULL) head = h;
if (tail != NULL)
{
tail->next = h;
}
tail = h;
h->next = NULL;
h->age = ....;
strncpy(h->age, "..name..", 100);
}
// ..... other code
// Remember to free all allocated memory
}
I'm not a great understanding on linked-list, i don't know if it's possible, but i need to do it :) I have a linked list that are load to the struct, and i need to compare a all the chars on the struct....It's better with an example:
This is without linked lists
struct
typedef struct x{
char name[100];
}x;
typedef x Info;
typdef struct Elem{
Info node;
struct Elem*next;
}Element;
for(i=0;i<100;i++){
if(strcmp(a.name[i],a.name[i+1])==0){
printf("Same name\n");
}
}
else
printf("Diff name\n");
Now i need to do something like this but with linked-list
First of all: int strcmp ( const char * str1, const char * str2 ) compares two C-strings (char pointers). This means that a.name[i] should be a char pointer and not a char! Make sure this is the case (i.e. make sure a.name is an array of c-string arrays, and not an array of chars).
Secondly, if the previous is the case, your code will only compare string i with string i+1. It will not compare all strings with each other.
In any case, it looks like you are not doing whatever it is you want to do the right way. I'm guessing you want a struct that is defined like this:
struct example {
char * name;
// other members of choice
example * next;
}
A placeholder for a name, other members, and a next pointer to enable the linked list data type. That way you can compare names with:
while (list->next != 0 && list->next->next != 0) {
if (strcmp(list->name, list->next->name) == 0) // do something;
else // do something else;
}
or with a double loop if you want to compare all strings with each other.
So the first thing you need to do is understand the fundamentals of linked-list. You can read in detail here: http://www.codeproject.com/KB/cpp/linked_list.aspx
NOTE: You really can't undersand linked lists until you understand pointers. http://www.cplusplus.com/doc/tutorial/pointers/
Essentially a linked-list is composed of numerous "nodes" that link to each other. At a minimum each node will have two pieces of data, one being the data (in your case a character) and the other being a pointer to the next node in the list.
Defining a struct would look like (in pseudocode):
LinkedList nodeT {
char *c; //NOTE: strcmp only compares pointers to chars
nodeT *nextNode;
}
You would have a pointer to the first node of the linked list. Something like:
nodeT *firstElement;
Then cycling through the entire list is a piece of cake:
nodeT *curElement = firstElement;
while(curElement->next != NULL) { //assuming the last node's next pointer is NULL
if(strcmp(curElement->c,curElement->next->c)==0){
printf("Same name\n");
} else {
printf("Diff name\n");
}
curElement = curElement->nextNode;
}
But again, to understand this you need to understand the fundamentals of pointers.
Here is a program that traverses the linked list and compares the names of adjacent elements. I have taken the liberty of renaming a couple of things, but otherwise the code for the data structures is the same as yours.
#include <string.h>
#include <stdio.h>
#include <assert.h>
typedef struct Info_ {
char name[100];
} Info;
typedef struct Element_ {
Info info;
struct Element_* next;
} Element;
void print_comparisons(Element* elm)
{
assert(elm);
Element* cur = elm;
Element* next = cur->next;
for (; next; cur = next, next = next->next) {
if (strcmp(cur->info.name, next->info.name) == 0)
printf("Same name\n");
else
printf("Diff name\n");
}
}
int main()
{
Info a; a.name[0] = 'A'; a.name[1] = '\0';
Info b; b.name[0] = 'B'; b.name[1] = '\0';
Info c; c.name[0] = 'B'; c.name[1] = '\0';
Info d; d.name[0] = 'D'; d.name[1] = '\0';
Element na; na.info = a;
Element nb; nb.info = b;
Element nc; nc.info = c;
Element nd; nd.info = d;
na.next = &nb;
nb.next = &nc;
nc.next = &nd;
nd.next = NULL;
print_comparisons(&na);
}
The output of the program:
Diff name
Same name
Diff name