C Programming: Linked Lists - linked-list

I'm writing a program using linked list (such a nightmare).
Anyway, the purpose of the program is to enter 8 characters and have the program print the characters back out to you and also print the characters back out in reverse order, using linked lists of course.
I got this so far. There's a lot wrong with it (i think).
Problems are
When asking for characters from the user it should read in the amount of characters automatically without having to ask for how many characters
Also, when it it compiles it prints gibberish to the screen, for example I just ran it and it printed
¿r
(àõ($ê¿¿
a¿r
(àõ($ê¿¿
¿r
(àõ($ê¿¿
b¿r
(àõ($ê¿¿
Lots of help needed here. It would be so much appreciated!
Code of course
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define strsize 30
typedef struct member
{
int number;
char fname[strsize];
struct member *next;
}
RECORD;
RECORD* insert (RECORD *it);
RECORD* print(RECORD *it, int j);
int main (void)
{
int i, result;
RECORD *head, *p;
head=NULL;
printf("Enter the number of characters: ");
scanf("%d", &result);
for (i=1; i<=result; i++)
head=insert (head);
print (head, result);
return 0;
}
RECORD* insert (RECORD *it)
{
RECORD *cur, *q;
int num;
char junk;
char first[strsize];
printf("Enter a character:");
scanf("%c", &first);
cur=(RECORD *) malloc(sizeof(RECORD));
strcpy(cur->fname, first);
cur->next=NULL;
if (it==NULL)
it=cur;
else
{
q=it;
while (q->next!=NULL)
q=q->next;
q->next=cur;
}
return (it);
}
RECORD* print(RECORD *it, int j)
{
RECORD *cur;
cur=it;
int i;
for(i=1;i<=j;i++)
{
printf("%s \n", cur->fname);
cur=cur->next;
}
return;
}

You have:
in insert:
char first[strsize];
scanf("%c", &first); /* note the %c */
strcpy(cur->fname, first);
in print
printf("%s \n", cur->fname);
You should have %s instead of %c and therefore change &format to format in the argument list, as format itself represents the address of the location the string is to be stored.
So the scanf call should be like below
scanf("%s", first);
Another thing. If you have specified a return type in the print function then you should return something, or make it return nothing (declare return type as void). This will not pose any problem in this case although.
Read the warning messages which the compiler throws to you and you would see the compiler actually had answered your questions.
You need to do some redesigns i think. For example to traverse the linked list you do not need to counter 'j'. you can detect the list termination by inspecting if the next link is NULL or not.
Your question was to print the characters or strings in reverse, so you need to write some other print function than what you have wrote.

Related

Converting the result from JSON GENERATE to EBCDIC

For one of my requirements I need the JSON GENERATE function in COBOL 6. My problem is, that it returns UTF-8, but I need the data in EBCDIC (CCSID 1140). Is there a way to convert this? Every solution I found uses national data types, but I have to use the NODBCS compiler option, so those don't work.
I do apologize for not first asking a question (but I am too new to StackOverflow to allow that.) The question would be "do you have C++ and can you link C++ with your COBOL?" I just tried this program:
#include <iconv.h>
class myConv
{
public:
static myConv globalConv;
size_t conv(char ** restrict f, unsigned int * restrict flen,
char ** restrict t, unsigned int * restrict tlen)
{
if (ok_)
{
return iconv(cd_, f, flen, t, tlen);
}
else
{
return (size_t)-1;
}
}
private:
myConv()
{
cd_ = iconv_open("1047", // EBCDID
"1208"); // UTF-8
ok_ = (cd_ != (iconv_t)-1);
// possibly indicate what the error is
}
~myConv()
{
if (ok_)
{
if (iconv_close(cd_) != 0)
{
// possibly indicate what the error is
}
}
}
bool ok_;
iconv_t cd_;
};
myConv myConv::globalConv;
extern "C" bool CNV(char * f, unsigned int flen,
char * t, unsigned int tlen)
{
return myConv::globalConv.conv(&f, &flen,
&t, &tlen) != (size_t)-1;
}
and the COBOL call looked like this:
json generate result from grp
call "CNV" using by reference result,
by value length of result,
by reference convertedres,
by value length of convertedres,
returning cres
and cres is a PIC S9(9) COMP data item which will have a non-zero value of the conversion succeeded.
Again, I apologize for not first asking if C++ is a possibility. (Or even C. The code could be easily done in C.) Also, the result is not quite perfect owing to the JSON GENERATE result being zero filled.

Getting segmentation fault when giving input to structure members on run time

I have written a small code to fetch info of 'n' number of students.
But after running the program, I'm getting a segfault. Please find the code below.
struct students
{
char name[20];
int age;
int id;
}student[100];
int main()
{
int count;
int no_students;
printf("Enter no of students");
scanf("%d",&no_students);
for (count = 1 ; count <= no_students ; count++)
{
printf("Enter the details for student%d\n",count);
printf("Name:");
scanf("%s",student[count].name);
printf("Age:");
scanf("%d",student[count].age);
printf("ID:");
scanf("%d",student[count].id);
}
return 0;
}
root#debian:/home/renga/C_code# ./nike
Enter no of students3
Enter the details for student1
Name:renga
Age:12
Segmentation fault
Got the problem, missed reference operator in scanf.
printf("Age:");
scanf("%d",&(student[count].age));
printf("ID:");
scanf("%d",&(student[count].id));
This may not be the right group to ask C language help/syntax question. I would recommend reading a good C programming language book ex: http://www.cprogramming.com/tutorial/c-tutorial.html
Having said that, the problem is, you are trying to read your int data type (age & id) values incorrectly. You need to read the values into the address of the variables as shown below...
scanf("%d",&student[count].age);

Is it possible to parse a string of fixed length in yacc/lex?

I have a file format something like this
...
{string_length} {binary_string}
...
example:
...
10 abcdefghij
...
Is this possible to parse using lexer/yacc? There is no null terminator for the string, so I'm at a loss of how to tokenize that.
I'm currently using ply's lexer and yacc for this
You can't do it with a regular expression, but you can certainly extract the lexeme. You're not specific about how the length is terminated; here, I'm assuming that it is terminated by a single space character. I'm also assuming that yylval has some appropriate struct type:
[[:digit:]]+" " { unsigned long len = atol(yytext);
yylval.str = malloc(len);
yylval.len = len;
for (char *p = yylval.str; len; --len, ++p) {
int ch = input();
if (ch == EOF) { /* handle the lexical error */ }
*p = ch;
}
return BINARY_STRING;
}
There are other solutions (a start condition and a state variable for the count, for example), but I think the above is the simplest.

I get a Suspicious pointer conversion in function main. How to get rid of this?

I'm new here at stackoverflow. The title is my question. Can someone please help me on this. Thanks. I've been working on this for like 3 days.
This part of code encodes the file to a huffman code
void encode(const char *s, char *out)
{
while (*s) {
strcpy(out, code[*s]);
out += strlen(code[*s++]);
}
}
This part of code deciphers the file from a huffman code to a human readable code
void decode(const char *s, node t)
{
node n = t;
while (*s) {
if (*s++ == '0') n = n->left;
else n = n->right;
if (n->c) putchar(n->c), n = t;
}
putchar('\n');
if (t != n) printf("garbage input\n");
}
This part is where I get my error.
int main(void)
{
int i;
const char *str = "this is an example for huffman encoding", buf[1024];
init(str);
for (i=0;i<128;i++)
if (code[i]) printf("'%c': %s\n", i, code[i]);
encode(str, buf); /* I get the error here */
printf("encoded: %s\n", buf);
printf("decoded: ");
decode(buf, q[1]);
return 0;
}
Declare 'buf' in a different line, and not as 'const':
char buf[1024];
The const applies to all the declarations on the line, so you're declaring buf as a const char[1024]. That means that calling encode casts away the constness, resulting in the warning.
Avoid having multiple variable declarations on the same line, unless they are all exactly the same type.

segmentation fault when printing a list of values from the memory

I am trying to make a small application that prints the content of a number of consecutive memory locations. As an indication of where the program is in the memory, I am printing the memory location of the main function and of a dummy variable.
In a first column, I want to print the address. In a second column, I want the contents of this address and the content of the 9 addresses behind it. In a third column, I want to print the byte value as a char, if it is printable. If it is not printable, I want to print a dot. In the rows under the first, I do exactly the same.
At startup, a number of values to print can be entered. If a positive value is entered, the addresses will increment, if a negative value is entered, the addresses will decrement.
To quickly see where I want to get to, you could run the code and enter for example 20 bytes to dump and use the address of the dummy as a starting address.
So far, my code only works for positive values. When I enter a negative number, I get a segmentation fault, but I can't figure out why. I tried to find the error in Valgrind, without success.
Some help would be greatly appreciated!
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define NUMBER_OF_BYTES 10
void showAddresses(void);
void printMemory(void);
void getDumpSize(void);
char* dummy; // dummy is een pointer naar een int
signed int dumpSize; // how many bytes have to be dumped?
signed int upDown; // do I need to go up or down?
int main(void)
{
dummy = (char *) malloc (sizeof(unsigned char));// memory allocation
showAddresses(); // prints the main function address and a variable address
getDumpSize(); //
printMemory(); //
free(dummy); // free memory
return 0; // end the main function
}
void showAddresses(void)
{
printf("Main function address is %p \n", main);
printf("Dummy variable address is %p \n",(void*)dummy);
}
void getDumpSize(void)
{
printf("Enter number of bytes to dump <negative or positive>:");
scanf("%d",&dumpSize);
if(dumpSize<0)
{
upDown = -1; // count down
printf("upDown was set to -1\n");
}
else
{
upDown = 1; // count up
printf("upDown was set to +1\n");
}
}
void printMemory(void)
{
int input;
printf("Enter the address:");
scanf("%x", &input); // enter the input
printf("Address \tBytes \t\t\t\tChars \n"); // print the table header
printf("--------- \t----------------------------- \t---------- ");
int i;
unsigned char* address; //
for(i=0;i<abs(dumpSize);i++)
{
address = (unsigned char*) (input+(i*upDown)); // make the address to print
if( (i%NUMBER_OF_BYTES) == 0) // show the address every 'i*NUMBER_OF_BYTES' times
{
printf("\n%p \t", (void*) address);
}
printf("%02x ", *address); // print as a 2 number hex and use zero padding if needed
if( (i%NUMBER_OF_BYTES) == (NUMBER_OF_BYTES-1) )// print the char list for every value (if printable)
{
printf("\t");
int j;
for(j=(NUMBER_OF_BYTES-1);j>=0;j--)
{
address = (unsigned char*) (input+(i*upDown)-j);
if(isprint(*address)==0)// print a dot if the byte value is not printable
{
printf(".");
}
else
{
printf("%c",*address); // print the byte value as a char, if printable
}
}
}
}
}
Your segmentation fault is likely coming from attempting to access memory outside of your program's scope. The address in "dummy" is the first malloc from your program, so it represents (possibly) the first "area" of memory available to your program. Going up from there might be keeping you in program space (hence the lack of seg fault), but going backward might be driving you into a restricted memory area. Out of curiosity: what is the memory address returned for your "dummy" malloc? Is the number even large enough to go backward without going negative? (I'm wondering if your program sees the true system memory map or a paged map that is already sand-boxed for programs.)

Resources