I am making a game where the answer is stored in client_challenges->answer while the client inputs the answer (which is stored in buffer) in the following format:
A: myanswer
If the answer starts from alphabet A, then i need to compare myanswer with the answer pre-stored. Using the code below, I get the correct buffer and ans lengths but if I print out my store array and answer array, the results differ. For example, if I input A: color, my store gives colo instead of color. However, store-2 works in some cases. How can I fix this?
if (buffer[0] == 'A')
{
printf("ans len %ld, buff len %ld\n",strlen(client_challenges->answer,(strlen(buffer)-4));
if(strlen(client_challenges->answer) == (strlen(buffer)-4))
{
char store[100];
for (int i = 1; i<= strlen(client_challenges->answer);i++)
{
store[i-1]=buffer[2+i];
}
store[strlen(store)-2] = '\0';
//store[strlen(client_challenges->answer)+1]='\0';
printf("Buffer: <%s>\n", buffer);
printf("STORE: %s\n",store);
printf("ANSWER: %s\n",client_challenges->answer);
if(strcmp(store,client_challenges->answer)==0)
{
send(file_descriptor, correct, strlen(correct), 0);
}
}
}
Example:
Client enters
A: Advancement
ans len 11, buff len 11
But when I print out store, it is Advancemen while the answer is Advancement. However, in my previous attempt, answer was soon and I entered "soon". It worked then.
Although I can not pin point the exact reason of this bug with the given input, I can share my experiences about how to find the correct spot efficiently.
Always verify your input.
Never trust an input. You only printed out the lengths of the inputs, what is the content. You'd better check with every byte (preferably in hex) to spot not printable characters. Some IDE provide integrated debugger to show buffer contents.
Use defines, constants, some human readable things instead of 4 or 2. This makes life much easier For instance
/* what is 4 here */
strlen(buffer)-4
should have been:
/* remove 'A: ' (A, colon, and white space, and I do not know what is 4th item */
strlen(buffer) - USER_ADDED_HEADERS
Get more familiar with C library
You actually did not need store array here. C provides strncmp function to compare two strings up to size "n" or memcmp to compare two buffers. This would save copy operation (cpu cycles), and stack memory.
More clear version of your code fragment (without error checks) could have been written as:
if (buffer[0] == 'A') {
/* verify input here */
/* #define ANSWER_START 4 // I do not know what the 4 is */
/* compare lengths here if they are not equal return sth accordingly */
/* supplied answer correct? */
if (memcmp(client_challenges->answer,
buffer + ANSWER_START,
strlen(client_challenges->answer)) == 0) {
/* do whatever you want here */
}
}
Consistent code formatting
Code formatting DOES matter. Be consistent on indents, curly parenthesis, tabs vs spaces, spaces before/after atoms etc. You do not have to stick to one format, but you have to be consistent.
Use a debugger
Debugger is your best friend. Learn about it. The issue with this bug can be identified with the debugger very easily.
Related
I am currently working on a program which involves creating a template for an exam.
In the function where I allow the user to add a question to the exam, I am required to ensure that I use only as much memory as is required to store it's data. I've managed to do so after a great deal of research into the differences between various input functions (getc, scanf, etc), and my program seems to be working but I am concerned about one thing. Here is the code for my function, I've placed a comment on the line in question:
int AddQuestion(){
Question* newQ = NULL;
char tempQuestion[500];
char* newQuestion;
if(exam.phead == NULL){
exam.phead = (Question*)malloc(sizeof(Question));
}
else{
newQ = (Question*)malloc(sizeof(Question));
newQ->pNext = exam.phead;
exam.phead = newQ;
}
while(getchar() != '\n');
puts("Add a new question.\n"
"Please enter the question text below:");
fgets(tempQuestion, 500, stdin);
newQuestion = (char*)malloc(strlen(tempQuestion) + 1); /*Here is where I get confused*/
strcpy(newQuestion, tempQuestion);
fputs(newQuestion, stdout);
puts("Done!");
return 0;
}
What's confusing me is that I've tried running the same code but with small changes to test exactly what is going on behind the scenes. I tried removing the + 1 from my malloc, which I put there because strlen only counts up to but not including the terminating character and I assume that I want the terminating character included. That still ran without a hitch. So I tried running it but with - 1 instead under the impression that doing so would remove whatever is before the terminating character (newline character, correct?). Still, it displayed everything on separate lines.
So now I'm somewhat baffled and doubting my knowledge of how character arrays work. Could anybody help clear up what's going on here, or perhaps provide me with a resource which explains this all in further detail?
In C, strings are conventionally null-terminated. Strlen, however, only counts the characters before the null. So, you always must add one to the value of strlen to get enough space. Or call strdup.
A C string contains the characters you can see "abc" plus one you can't which marks the end of the string. You represent this as '\0'. The strlen function uses the '\0' to find the end of the string, but doesn't count it.
So
myvar = malloc(strlen(str) + 1);
is correct. However, what you tried:
myvar = malloc(strlen(str));
and
myvar = malloc(strlen(str) - 1);
while INCORRECT, MAY seem to work some of the time. This is because malloc typically allocates memory in chunks, (say maybe in units of 16 bytes) rather than the exact size you ask for. So sometimes, you may 'luck out' and end up using the 'slop' at the end of the chunk.
I'm learning C from K&R's "The C Programming Language" book. I'm doing the exercises specified in the book. I'm on exercise number 1.16, but I don't understand it.
Exercise 1.16:
Revise the main routine of the longest-line program so it will
correctly print the length of arbitrarily long input lines, and as
much as possible of the text.
My questions:
"...as much as possible of the text..." - is there some limitation on string length? Maybe in standard headers there's a variable with the max allowed value of string length?
"...the length of arbitrarily long input lines..." - but in the code MAXLINE is defined as 1000. It is limited size too. I see some solutions here, but in my opinion it is not solution decision, since on the former there is a restriction on length of a line (1000 characters).
Maybe I don't understood the task. My understanding is I must remove the 1000-character limitation.
It's a pretty early exercise in K&R, you're just supposed to do some minor changes to the code, not a total redesign of the code.
"...as much as possible of the text..."
is up to you to interpret. I'd do it by printing what's stored in the longest buffer. i.e. print out up to 1000 characters of the line. Again, it's an early exercise, with little introduction to dynamically allocated memory yet. And at the time K&R was written, storing away arbitrarily long text lines wasn't as feasible as it is today.
"...the length of arbitrarily long input lines..."
Is a hard requirement. You're supposed to find the correct length no matter how long it is (at least within the bounds of an int. )
One way to solve this problem is:
After the call to getline(), check if the last character read into the line buffer is a newline ('\n')
If it is, you read a complete line. The len variable is the correct length of the line(the return value of getline(), and no special consideration is needed compared to to original code.
If it is not , you did not read the entire line, and need to hunt for the end of this line. You add a while loop, calling getchar() until it returns a newline (or EOF), and count the number of characters you read in that loop. Just do len++ to count.
When the while loop is done, the new len is now the actual length of the line, but our buffer just has the first 999 characters of it.
As before, you store away (the copy() function call) the current line buffer (max 1000 chars) if this line is the longest so far.
When you're done, you print out the stored line as before (the longest buffer) and the max variable for the length.
Due to the above mentioned while loop that max length is now correct.
If the longest line indeed was longer than 1000 chars. you at least print out those first 999 chars - which is "as much as possible".
I'll not spoil it and post the code you need to accomplish this, but it is just 6 lines of code that you need to add to the longest-line program of exercise 1-16.
On modern machines "as much as possible of the text" is likely to be all of the text, thanks to automatically line-wrapping terminal programs. That book was written when teletype terminals were still in use. There is no limitation on string length other than perhaps memory limitations of the machine you're working on.
They're expecting you to add some kind of loop to read characters and look for newlines rather than assuming that a read into the MAXLINE sized buffer is going to contain a newline for sure.
here is my version:
int getline(char s[],int lim)
{
int c,i;
for(i=0;i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i)
s[i]=c;
if(c=='\n')
{
s[i]=c;
++i;
}
if(c!=EOF)
{
while((c=getchar())!=EOF&&c!='\n')
i++;
}
s[i]='\0';
return i;
}
#define MAXLINE 1000
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max=0;
while((len=getline(line,MAXLINE))>1)
{
if(len>max)
{
max=len;
copy(longest,line);
}
}
if(max>0)
{
printf("%d:%s",max,longest);
}
return 0;
for some unknown reasons ,the example code doesn't work in my pc
particularly,when the condition is 'len>0',the loop won't end
i think the main reason is that when you type nothing,but you still have to press enter,so it is received as '\n',and the len is 1;
i think it satisfy the requirement that print the length of arbitrarily long input lines, and as much as possible of the text.
And it works like this
#include
main()
{
long tlength = 0;
short input, llength = 1;
while (llength > 0) {
llength = 0;
while ((input = getchar()) != EOF) {
++llength;
if (input == '\n')
break;
}
tlength = tlength + llength;
printf("\nLength of just above line : %5d\n\n", llength);
}
printf("\n\tLength of entire text : %8ld\n", tlength);
return 0;
}
According to me, This question only wants the length of each arbitrarily line + At last the length of entire text.
Try to run this code and tell me is it correct according to question because i too confuse in this problem.
I want to offer that this exercise actually makes more sense if imagine that the limit of the number of characters you can copy is very small -- say, 100 characters -- and that your program is supposed to judge between lines that are longer than that limit.
(If you actually change the limit so that it's very small, the code becomes easier to test: if it picks out the first line that hits that small limit, you'll know your code isn't working, whereas if it returns the first however-many characters of the longest line, it's working.)
Keep the part of the code that copies and counts characters until it hits a newline or EOF or the line-size-limit. Add code that picks up where this counting and copying leaves off, and which will keep counting even after the copying has stopped, so long as getchar() still hasn't returned an EOF or a newline.
My solution: just below the call to getLine
if ( line[len-1] != '\n' && line[len-1] != EOF) //if end of line or file wasnt found after max length
{
int c;
while ( ( c = getchar() ) != '\n' && c != EOF )
len++; //keep counting length until end of line or file is found
}
to test it, change MAXLINE to 25
I am currently working with parsing some MAC addresses. I am given an output that does not include leading zeros (like so).
char* host = "0:25:25:0:25:25";
and I would like to format it like so
char* host = "00:25:25:00:25:25";
What would be the easiest way to go about this?
For those wondering, I am using the libpcap library.
I may be missing something in the question. Assuming you know it is a valid MAC, and the input string is thus parsable, have you considered something as simple as:
char* host1 = "0:25:25:0:AB:25";
char *host2 = "0:1:02:3:0a:B";
char result[19];
int a,b,c,d,e,f;
// the question sample
if (sscanf(host1, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host1: %s\n", result);
// a more daunting sample
if (sscanf(host2, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host2: %s\n", result);
Output
host1: 00:25:25:00:AB:25
host2: 00:01:02:03:0A:0B
Obviously for the ultra-paranoid you would want to make sure a-f are all < 255, which is probably preferable. The fundamental reasons I prefer this where performance isn't a critical issue are the many things you may not be considering in your question. It handles all of
Lead values of "n:", where n is any hex digit; not just zero. Examples: "5:", "0:"
Mid values of ":n:", again under the same conditions as (1) above. Examples: ":A:", ":0:"
Tail values of ":n". once more, under the same conditions as (1) above. Examples: ":b", ":0"
Hex-digit agnostic when reading; it works with both upper and lower case digit chars.
Most important, does nothing (except upper-case the hex values) if your input string is already properly formatted.
Roughly like this:
Allocate an output string to hold the reformatted MAC address.
Iterate over the input string and use strtok with : delimiter. In each iteration convert the beginning of the string (2 bytes) into a numerical value (e.g., with atoi). If the result < 16 (i.e., < 0x10), set "0" into the output string at current position and the result in hex at the following position; otherwise copy the 2 bytes of input string. Append : to the output string. Continue till end of the input.
This code comes from K&R. I have read it several times, but it still seems to escape my grasp.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
return(bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE)
printf("too many characters");
else buf[bufp++]=c;
}
The purpose of these two functions, so K&R says, is to prevent a program from reading too much input. i.e. without this code a function might not be able to determine it has read enough data without first reading too much. But I don't understand how it works.
For example, consider getch().
As far as I can see this is the steps it takes:
check if bufp is greater than 0.
if so then return the char value of buf[--bufp].
else return getchar().
I would like to ask a more specific question, but I literally dont know how this code achieves what it is intended to achieve, so my question is: What is (a) the purpose and (b) the reasoning of this code?
Thanks in advance.
NOTE: For any K&R fans, this code can be found on page 79 (depending on your edition, I suppose)
(a) The purpose of this code is to be able to read a character and then "un-read" it if it turns out you accidentally read a character too many (with a max. of 100 characters to be "un-read"). This is useful in parsers with lookahead.
(b) getch reads from buf if it has contents, indicated by bufp>0. If buf is empty, it calls getchar. Note that it uses buf as a stack: it reads it from right-to-left.
ungetch pushes a character onto the stack buf after doing a check to see if the stack isn't full.
The code is not really for "reading too much input", instead is it so you can put back characters already read.
For example, you read one character with getch, see if it is a letter, put it back with ungetch and read all letters in a loop. This is a way of predicting what the next character will be.
This block of code is intended for use by programs that make decisions based on what they read from the stream. Sometimes such programs need to look at a few character from the stream without actually consuming the input. For example, if your input looks like abcde12xy789 and you must split it into abcde, 12, xy, 789 (i.e. separate groups of consecutive letters from groups of consecutive digits) you do not know that you have reached the end of a group of letters until you see a digit. However, you do not want to consume that digit at the time you see it: all you need is to know that the group of letters is ending; you need a way to "put back" that digit. An ungetch comes in handy in this situation: once you see a digit after a group of letters, you put the digit back by calling ungetch. Your next iteration will pick that digit back up through the same getch mechanism, sparing you the need to preserve the character that you read but did not consume.
1. The other idea also shown here can be also called as a very primitive I/O stack mangement system and gives the implementation of the function getch() and ungetch().
2. To go a step further , suppose you want to design an Operating System , how can you handle the memory which stores all the keystrokes?
This is solved by the above code snippet.An extension of this concept is used in file handling , especially in editing files .In that case instead of using getchar() which is used to take input from Standard input , a file is used as a source of input.
I have a problem with code given in question. Using buffer (in form of stack) in this code is not correct as when getting more than one extra inputs and pushing into stack will have undesired effect in latter processing (getting input from buffer).
This is because when latter processing (getting input) going on ,this buffer (stack) will give extra input in reverse order (means last extra input given first).
Because of LIFO (Last in first out ) property of stack , the buffer in this code must be quene as it will work better in case of more than one extra input.
This mistake in code confused me and finally this buffer must be quene as shown below.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufr = 0;
int buff = 0;
int getch(void)
{
if (bufr ==BUFSIZE)
bufr=0;
return(bufr>=0)?buf[bufr++]:getchar();
}
int ungetch(int c)
{
if(buff>=BUFSIZE && bufr == 0)
printf("too many characters");
else if(buff ==BUFSIZE)
buff=0;
if(buff<=BUFSIZE)
buf[buff++]=c;
}
I'm trying to use Mac OS X's listxattr C function and turn it into something useful in Python. The man page tells me that the function returns a string buffer, which is a "simple NULL-terminated UTF-8 strings and are returned in arbitrary order. No extra padding is provided between names in the buffer."
In my C file, I have it set up correctly it seems (I hope):
char buffer[size];
res = listxattr("/path/to/file", buffer, size, options);
But when I got to print it, I only get the FIRST attribute ONLY, which was two characters long, even though its size is 25. So then I manually set buffer[3] = 'z' and low and behold when I print buffer again I get the first TWO attributes.
I think I understand what is going on. The buffer is a sequence of NULL-terminated strings, and stops printing as soon as it sees a NULL character. But then how am I supposed to unpack the entire sequence into ALL of the attributes?
I'm new to C and using it to figure out the mechanics of extending Python with C, and ran into this doozy.
char *p = buffer;
get the length with strlen(p). If the length is 0, stop.
process the first chunk.
p = p + length + 1;
back to step 2.
So you guessed pretty much right.
The listxattr function returns a bunch of null-terminated strings packed in next to each other. Since strings (and arrays) in C are just blobs of memory, they don't carry around any extra information with them (such as their length). The convention in C is to use a null character ('\0') to represent the end of a string.
Here's one way to traverse the list, in this case changing it to a comma-separated list.
int i = 0;
for (; i < res; i++)
if (buffer[i] == '\0' && i != res -1) //we're in between strings
buffer[i] = ',';
Of course, you'll want to make these into Python strings rather than just substituting in commas, but that should give you enough to get started.
It looks like listxattr returns the size of the buffer it has filled, so you can use that to help you. Here's an idea:
for(int i=0; i<res-1; i++)
{
if( buffer[i] == 0 )
buffer[i] = ',';
}
Now, instead of being separated by null characters, the attributes are separated by commas.
Actually, since I'm going to send it to Python I don't have to process it C-style after all. Just use the Py_BuildValue passing it the format character s#, which knows what do with it. You'll also need the size.
return Py_BuildValue("s#", buffer, size);
You can process it into a list on Python's end using split('\x00'). I found this after trial and error, but I'm glad to have learned something about C.