I'm learning queues and I came across this piece of code. It's from a book, so I can't post the whole code here but what I'm posting will be sufficient. More than a problem, I just want to confirm that whether my understanding of this code is correct or not.
In the function, delete_ap(), the 'if' statement calls qretrieve() function and stores its return value in pointer 'p'.
My problem is: If the value returned is not NULL, then too the 'if' statement is executed, isn't it?
So a value is still stored in 'p' and we can just print this value without using an 'else' statement as used in this example.
Thanks!
/* Delete an appointment from the queue. */
void delete_ap(void)
{
char *p;
if((p=qretrieve()) ==NULL) return;
printf("%s\n", p); <--Problem is in this line and the one above it.
}
/* Retrieve an appointment. */
char *qretrieve(void)
{
if(rpos==spos) /* spos:holds the index of the next free storage location.
rpos:holds the index of the next item to retrieve.*/
{
printf("No more appointments.\n");
return NULL;
}
rpos++;
return p[rpos-1];
}
This is the same as:
char *p = qretreive(); // <-- will always execute
if(p==NULL)
return; // <-- will not execute the next line if p is invalid
printf("%s\n", p);
The return statement is used instead of putting the rest of the function in an else block.
That is, the execution will only reach printf if p != NULL.
Note: Many people argue that returns in the middle of the code makes the code hard to read and prone to bugs due too missing cleanup that is usually done at the end of the method.
Related
When I call the print_linklist function I am getting a segmentation fault. Here is the function definition:
//will display the node in a nice string
char * term_to_string(term_t * term){
int exp = term->exponent;
int coef = term->coefficient;
return ("%dx^%d", coef, exp);
}
**//will print the list using the nodde_to_string method
void print_linklist(node_t * curr){
printf("entering print to list!!!");
node_t * current = curr;
while(current != NULL){
printf("%s +", term_to_string(curr->term));
current = current->next_node;
}
}**
And here is the main method where it is being called:
/* This is your main file */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"
#include"buildlinklist.h"
#include"printandcombine.h"
int main() {
node_t * node_ptr = NULL;
node_t * new_node_ptr=NULL;
printf("NAME: SAMPLE OUTPUT\n");
/* Build linklist */
read_objects(&node_ptr);
/* Print the link list */
printf("Original: \n");
print_linklist(node_ptr);
/* Combine like terms in the link list and craeate a new link list */
new_node_ptr=combine_like_terms(node_ptr);
printf("\nCombined: : ");
/* Print new combine linklist */
print_linklist(new_node_ptr);
printf("\nNAME: SAMPLE OUTPUT\n");
free(node_ptr);
free(new_node_ptr);
return 0;
}
After the function is called I get "zsh: segmentation fault ./project1". I don't even get the "entering print to list!!!" to print from the print_linklist method.
return ("%dx^%d", coef, exp);
That's not doing what you seem to think it's doing (what I think you think it's doing is to return a string created by some sort of printf functionality).
However, the comma operator in something like a, b evaluates both a and b, but the result is b. The n-variant, like a, b, c, d, evaluates everything and returns the last one (d).
Hence you are returning exp as if it was a character pointer. It almost certainly isn't (since you're trying to printf it with %d) so, if you treat it as such, hilarity may ensue.
Well, less hilarity and more crashing/weirdness, but you get the idea :-)
You could create strings in heap memory and pass them around but it's sometimes difficult for newcomers to the language to do that safely. Instead, I would suggest simply printing the thing within the function, with something like:
void print_term(const term_t *term, const char *after){
printf("%dx^%d%s", term->coefficient, term->exponent, after);
}
void print_linklist(node_t *curr){
puts("entering print to list!!!");
node_t *current = curr;
while (current != NULL){
print_term(curr->term, " +");
current = current->next_node;
}
}
You'll notice my "entering print to list" statement is subtly different to yours in that it uses puts, which appends a newline character to the end (you could do that explicitly, with \n, if you wanted to stick with printf).
Since standard output is line-buffered for terminal devices, the reason you're not seeing that is almost certainly due to the fact your code is crashing (as per this answer) before it flushes. In that case, unflushed data is likely to just disappear.
There could be a number of reasons you are getting a segmentation fault but trying to print the list is not one of them. If your read_objects() declaration is like this read_objects(node_t * curr) then you shouldn't pass as an argument the address of the pointer
read_objects(&node_ptr);
This should be read_objects(node_ptr);
Also, if you want to iterate through the list and print it you should create a pointer to the head of the list in the main() function node_t *head = NULL;
and pass it as a parameter in the print_linklist(head);.
After that, make *current point at the head of the list node_t * current = head;.
That way you are starting printing the nodes from the start. You should also check if the list is empty.
I don't even get the "entering print to list!!!" to print from the print_linklist method.
printf doesn't cause anything to be printed to the screen. It just copies a string into a buffer to be printed at some later time. If you want to force the buffer to be printed, you can call fflush. As mentioned in comments, if stdout is directed to an interactive device, including a \n in the output string will generally also cause the buffer to be flushed to the actual output device.
After the function is called I get "zsh: segmentation fault ./project1".
This probably happens in term_to_string if you call it with an invalid pointer argument, when it tries to dereference its argument.
Hi everyone I have a problem taking care of a malfunction, I'm building a dynamic linked list which connects structures with *next and *previous,
now if the structures are unable to connect (long story) I need to print "the way does not exist" now I've made an if statement
temp = point_start; // point_start is the head of the list
condition = 2;
for(i=0;i<gagnum;i++) //gagnum is the number of structures
{
temp=point_start->previous; // previous is the pointer of the previous structure.
if (temp != 0xcdcdcdcd) // ------> is this legal?
condition = 1;
else
{
printf("no route found ")
condition = 2;
break;
}
}
I have an if statement which says "if (temp != 0xcdcdcdcd)" so when it gets garbage I put out the message and stop the program, is this legal to use? is there a better way to do this? thank you so much for your help!
Instead of using 0xcdcdcdcd, you should be using 0x0 to indicate a NULL pointer.
Here's a function which does what I think you're trying to do:
// checks to see if the given list is the "first" structure
bool is_first_structure(void* head)
{
return head->previous != NULL;
}
And here's how to use it:
if(!is_first_structure(head))
{
printf("no route found");
}
Hi the answer to the problem is just to NULL all your pointers when you're building the linked list. then check if the pointer is NULL instead of garbage, hope it helps!
Wikipedia writes for 0xcdcdcdcd
Used by Microsoft's C/C++ debug malloc() function to mark uninitialized heap memory, usually returned from HeapAlloc()
So I guess you malloc a node and not initializing the pointers.
I have the following structure and have some code to use it below. The control is not going into the if statement(I need to check if the chat_info[queue].message is empty which it is)
struct chat{
char message[MAXNAME];
int client;
int group;
int flag;
};
.
.
.
.
if(filedata.data==NULL)
{
printf("\n data is %s",filedata.data);} //displays "data is "
chat_info[queue].message[0]='\0'; //setting 0 before copying data
strcpy(chat_info[queue].message,filedata.data);
printf("\n data is %s",chat_info[queue].message);//displays "data is "
if(chat_info[queue].message[0]=='\0'){
// not going into this if statement
//I also tried if(chat_info[queue].message== "") and if(chat_info[queue].message== NULL)
}
The first issue I see:
if (filedata.data == NULL)
Which can also be written as:
if (!filedata.data)
Once inside the if-statement you attempt to copy the contents of filedata.data into chat_info[queue].message. However, we previously established that filedata.data points to nothing. It is NULL. Using strcpy() with a NULL pointer as the source should not work.
Perhaps you meant:
if (filedata.data != NULL)
Which can also be written as:
if (filedata.data)
Secondly, if filedata.data wasn't NULL, think about when chat_info[queue].message[0] == '\0' would be true.
strcpy(chat_info[queue].message, filedata.data);
if(chat_info[queue].message[0] == '\0') {
// Message was determined to be empty.
}
It would only be true if the filedata.data was an empty string. (Note: this is different than being NULL!) Is that what you want? If so, the current code should work fine.
Reference: strcpy() documentation
What is the type for message? Because, if it is a string, then it will implicitly cast when you set it to a char = '\0';. Perhaps, you need to do:
if (chat_info[queue].message[0] == "\0")
strcpy(chat_info[queue].message,filedata.data);
/* You have assigned some data for chat_info[queue].message
* in the above step assignment should be successful.
*/
if(chat_info[queue].message[0]=='\0')
/* How can message[0] be null? It will never be. Think of what you're
* trying to achieve with the condition.
* If you're checking for a non-empty message, then it should be
* chat_info[queue].message[0]!='\0'
*/
{
./* some stuff here */
}
My code, which gets called when you type "recent":
char* runRecent() {
FILE *ffp;
ffp = fopen("bash.txt","r");
char line[MAXLINE];
int fileItCount = 0;
for (int i = 0 ; i < numLinesinFile ; i++) {
fgets(line, sizeof(line), ffp);
if (fileCounter - 2 < 0){
printf("No recent commands exist.\n");
exit(EXIT_FAILURE);
}
if (i == (numLinesinFile - 2) && i >= 0) {
printf("Previous command: %s\n",line);
char * lineRet = strdup(line);
printf("line ret: %s\n",lineRet); //output: correct, something along the lines of "ls" or "ls -a"
printf("line ret: %d\n",&lineRet); //output: 1528174960
return lineRet;
}
}
}
The lineRet then gets passed to a function:
start(runRecent());
Where the function declaration looks like:
void start(char inputBuf[]){
printf("input is %s\n",inputBuf); //prints the command "recent" instead of the previous command that was executed
}
Why is this returning the current command instead of the previous one?
Your code has many issues,
The function does not always return a value, which can lead to undefined behavior in case the function never reaches the return statement. It is very clear why this could be the cause so I will not explain it in detail.
You can just add a default return like return NULL; at the end of the function, but then you have to check for NULL before passing the result to printf().
It also invokes undefined behavior here
printf("line ret: %d\n", &lineRet);
one of the possible explanations of your observed behavior is undefined behavior, the right way to print a pointer is
printf("line ret: %p\n", (void *) &lineRet);
anything else is considered undefined behavior by the standard.
Not checking that strdup() did not return a NULL poitner, which can happen if there is no available memory. This is very unlikely the problem, but you must check if you want your program to work under any conditions.
Not checking that fopen() did not return NULL, which can be the case when for example the file is not readable to the current user or it does not exist at all, in any case when it's not possible to open it.
start(runRecent()); automatically causes a memory leak, you don't need to free every single malloc() because memory will be released automatically when the program ends. But a few mistakes like this and you will be in serious trouble, specially because you don't check if strdup() returned a non-NULL pointer.
It turns out that it's not so hard to write a program that will eat all the system available memory, a tiny memory leak an a few minutes running are sufficient for it to happen.
NOTE: Enable compiler warnings and you would both, not ask this kind of question ever and learn more about the c language just by simple induction.
I'm having trouble using strstr. Here's what I have:
Passing character array of length 21 bytes to a function.
Traversing through nodes of a linked list, comparing each node's character array with the above array passed as mentioned in point 1
strstr is always returning NULL irrespective of any string passed
Let's say for example code like strstr("hello","he"). It should return pointer to "hello", but that never happens in my code below. It is always returns NULL.
Here is the code snippet of the program:
void display_to_file(const char *chr,c_uint32 pos_in_list,c_uint32 line_no)
{
NODE *search = ptrs_to_heads_of_alpha[pos_in_list];
char *chk;
char redundant[21]={'\0'};
int first=1;
uint32 count = 0;
while((NULL!=search) && (count<21))
{
printf("\nsearch->arg=%s",search->arg); /*for example search->arg is "hello"*/
/*above statement prints "hello"-correctly*/
/*for example chr="?he" */
printf("\nchr=%s",&chr[1]); /*prints "he" correctly*/
chk=strstr(search->arg,&chr[1]);
if(chk != NULL) /*is always null- not known why it returns null even for valid cases*/
{
printf("\nentered_\n");
++count;
if(1 == first)
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
printf("\nop:%s\n",search->arg);
first = 0; /*only for first node print*/
}
else
{
if(strcmp(redundant,search->arg) == 0)/*duplicate found*/
--count; /*need to search for one more item*/
else
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
}
}
}
else
printf("\nelse,else,else\n\n"); /*Always this statement is executed even
if I passed valid arguments*/
search=search->next;
}
}
is there any warning with this statement at compile time?:
chk=strstr(search->arg,&chr[1]);
2nd argument should be const char * in strstr()
make sure this thing.
One more thing try with this statement
chk=strstr(search->arg,"he");
one more thing check you have included string.h
#include<string.h>
Try embracing string with quotes (or another noticeable symbol), because there could be space characters, for example, which you don't see. So replace
printf("%s\n", some_string);
with
printf("\"%s\"\n", some_string);
I recommend to always use embracing with "printf-debugging". However, your problem could be somewhere else. Try to shorten your program for finding an error.