I made a simple code in VS Code, hello world, then I run and it worked. Next, I added an input, scanf. But when I run the code, the output is empty. The output doesn't show anything and only says "running". Please help me solve this.
First code (success):
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
Second code (failed):
#include <stdio.h>
int main()
{
int pin;
printf("Hello World");
scanf("%d", &pin);
return 0;
}
My code just accept printf, not scanf. If I add scanf, the output is empty and keep running. If I remove scanf and only printf in my code, is successful.
The printf function writes to stdout. When stdout is connected to a terminal or console, it's line buffered.
Line buffering means that the output is actually written to the terminal/console on either of three conditions:
The buffer is full
The buffer is explicitly flushed with fflush(stdout)
A newline is printed.
Your output:
printf ("Hello World");
doesn't fulfill any of the three conditions.
Simple solution is to add a trailing newline in the output you print:
printf ("Hello World\n");
Well you have not told your code to actually do anything with the scanf, that's maybe why nothing has come up on your terminal. scanf only takes input from the terminal, but it will not spit it out without you telling it to.
you will need to include this line of code for that to happen:
printf("%d", pin); // underneath your scanf line.
Related
I have a process which does multiple forks, generating several sub processes which have to write on stdout. So, the messages of the different sub processes might cross with themselves. How can I avoid this problem?
Say you have three processes, each trying to output an infinite series of lines composed of four characters followed by a newline:
void four(char c);
int main()
{
//insert your own error checking
pid_t p0, p1, p2;
#define PROC(pid,str) pid=fork(); if(0==pid) four(str);
PROC(p0,'a');
PROC(p1,'b');
PROC(p2,'c');
waitpid(p2, 0,0);
waitpid(p1, 0,0);
waitpid(p0, 0,0);
}
If your four function is:
void four(char c)
{
for(;;){
for(int i=0; i<4;i++)
putchar(c);
putchar('\n');
}
}
and you pipe your program into this grep invocation:
./a.out |grep -v -e aaaa -e bbbb -e cccc
You'll get matches that demonstrate your problem.
The easiest way to solve this is by relying on the Linux guarantee that it won't break write calls aimed at a pipe if the write arguments are smaller than the pipe buffer size (defaults to 4KiB on my system (you can get the size from the ulimit shell builtin).
void four(char c)
{
for(;;){
for(int i=0; i<4;i++)
putchar(c);
putchar('\n');
fflush(stdout);
//the stdout buffer is surely larger than 5
//so this is 1 `write`
}
}
If you want to be more portable and robust, you can use a lock on a shared file:
void four(char c)
{
int fd;
fd = open("/proc/self/exe", O_RDONLY);
for(;;){
if(0>flock(fd, LOCK_EX))
perror("flock");
for(int i=0; i<4;i++)
{ putchar(c); fflush(stdout); }
putchar('\n'); fflush(stdout);
//the pipe buf guarantee won't save us here
//given all these flushes
//but this lock will
if(0>flock(fd, LOCK_UN))
perror("flock");
}
}
Alternatively, can also set file locks with fcntl.
By "cross themselves", I presume you mean that you are worried about output being interleaved. That is, one process attempts to output "Hello, World!", while another prints "Goodbye, Chicago!", and the final output is "Hello, Goodby, World! Chicago!", or similar. The absolute simplest approach to solving this is to ensure that each message you write is written with a single write system call, and that the data is small. If your messages are less than 1k (or so, the exactly value is system dependent, often 4096, rarely less than 512). If you invoke write with a sufficiently small buffer, the write will be atomic and will not be interleaved with output from any other process. If your messages won't fit in the size for the system you are on, you will need to use some locking mechanism.
I am using SIM900 GPS/GPRS module shield connected to an Arduino Uno, how will I be able to parse the response of my AT commands? Or how will I be able to remove the 1st line printed in the serial after sending an AT command?
AT+CMGL="ALL"
+CMGL: 1,"REC READ","+XXXXXXXXXX","","16/04/25,15:20:59+32"
Hilp akp si ralphh the pogi one mmalit mi pizza hehehehehe
+CMGL: 2,"REC READ","+XXXXXXXXXX","","16/04/25,21:51:33+32"
Yow!!!
OK
Example on the output above, I want to get rid of the AT+CMGL="ALL" and then parse the data left. What is the best way in parsing?
How will I be able to parse the response of my AT commands?
Yes, this is the right question to ask.
How will I be able to remove the 1st line printed in the serial after sending an AT command?
No, this is the wrong question to ask, because if you care about whether echo is on or not you are doing it wrong.
The correct strategy for parsing AT command output is as follows:
Send the AT command line (correctly terminated with "\r").
Read one and one character received from the modem until you have a complete line terminated with "\r\n" and then parse that line.
If the line equals a final result code, then all output from the command line is finished (and the modem is ready to receive new commands). This must be the first thing you test for!
If the AT command running has a prefix for its information text response lines (almost all have) check if the line starts with that, and if so process the line else ignore it.
If the AT command running does not have a prefix you probably want to print everything until the final result code is received. This applies only for legacy commands like ATI, and for parsing these you might legitimately care about echo or not.
Now for the AT+CMGL command it is a little bit more work since the responses are split on multiple lines.
First of all, the best source of information should be the manufacturer specific AT documentation, the second best being the official 3GPP 27.005 specification that standardize the AT+CMGL command.
The response for AT+CMGL in text mode is specified as
+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[<CR><LF>
+CMGL: <index>,<stat>,<da/oa>,[<alpha>],[<scts>][,<tooa/toda>,
<length>]<CR><LF><data>[...]]
hence after receiving a line starting with "+CMGL: " all the lines following until you read a blank line ("\r\n") belongs to this.
See this answer on the general code structure and flow, although as written above the multi-line property of the response needs a bit more handling. I would have used something like the following (untested code):
enum CMGL_state {
CMGL_NONE,
CMGL_PREFIX,
CMGL_DATA
};
// Extra prototype needed because of Arduino's auto-prototype generation which often breaks compilation when enums are used.
enum CMGL_state parse_CMGL(enum CMGL_state state, String line);
enum CMGL_state parse_CMGL(enum CMGL_state state, String line)
{
if (line.equals("\r\n") {
return CMGL_NONE;
}
if (line.startsWith("+CMGL: ") {
return CMGL_PREFIX;
}
if (state == CMGL_PREFIX || state == CMGL_DATA) {
return CMGL_DATA;
}
return CMGL_NONE;
}
...
write_to_modem("AT+CMGL=\"ALL\"\r");
CMGL_state = CMGL_NONE;
goto start;
do {
CMGL_state = parse_CMGL(CMGL_state, line);
switch (CMGL_state) {
case CMGL_PREFIX:
process_prefix(line); // or whatever you want to do with this line
break;
case CMGL_DATA:
process_data(line); // or whatever you want to do with this line
break;
case CMGL_NONE:
default:
break;
}
start:
line = read_line_from_modem();
} while (! is_final_result_code(line))
The first line AT+CMGL="ALL" seems to be the echo. You can disable it by sending ATE0 to your module in your setup function.
As for the rest of the data, it all have the same format. You can easily write your parser using different string manipulation functions.
If you are using arduino I would recommend to use a good library! You don't need to deal about these stuff. Try http://www.gsmlib.org/ or you can find any other you like.
I will include one example here.
#include "SIM900.h"
#include <SoftwareSerial.h>
//If not used, is better to exclude the HTTP library,
//for RAM saving.
//If your sketch reboots itself proprably you have finished,
//your memory available.
//#include "inetGSM.h"
//If you want to use the Arduino functions to manage SMS, uncomment the lines below.
#include "sms.h"
SMSGSM sms;
//To change pins for Software Serial, use the two lines in GSM.cpp.
//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.
//Simple sketch to send and receive SMS.
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
void setup()
{
//Serial connection.
Serial.begin(9600);
Serial.println("GSM Shield testing.");
//Start configuration of shield with baudrate.
//For http uses is raccomanded to use 4800 or slower.
if (gsm.begin(2400)){
Serial.println("\nstatus=READY");
started=true;
}
else Serial.println("\nstatus=IDLE");
if(started){
//Enable this two lines if you want to send an SMS.
//if (sms.SendSMS("3471234567", "Arduino SMS"))
//Serial.println("\nSMS sent OK");
}
};
void loop()
{
if(started){
//Read if there are messages on SIM card and print them.
if(gsm.readSMS(smsbuffer, 160, n, 20))
{
Serial.println(n);
Serial.println(smsbuffer);
}
delay(1000);
}
};
I am trying to create pipe and use it with fork(). But I m confused in the order of execution.
Process reads data from pipe before anything is written into pipe. Sometimes it runs correctly. But sometimes, reads before writing but still gives correct output.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2], nbytes,ret;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[80];
pipe(fd);
if(!fork())
{
close(fd[0]);
printf("Writing...");
write(fd[1], string, (strlen(string)+1));
exit(0);
}
else{
close(fd[1]);
printf("Reading...");
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
wait(NULL);
}
return 0;
}
It happens because scheduler schedules the parent process before the child and thus
it results in the read operation before write. On the other hand, the output may be
as expected sometimes when scheduler will schedule the child first.
SOLUTION:
1. you need to use synchronisation techniuqes like semaphores in order to synchronise the
parent and the child.
2. or you can make the parent process wait until the child has finished. Consider the
following code :
int child_status; // declare this variable
/* add the following line to the else clause */
else
{
close(fd[1]);
wait(&child_status);
// rest of your code
}
Explanation :
If the parent process is scheduled before the child, then its execution will halt when
it finds the 'wait(&child_status)' statement and will wait for the child to finish
its execution and then proceed further.
Example code
int main(int, char * argv[]) {
QString input = QTextStream(stdin).readLine();
QTextStream(stdout) << input << "\nWe need to go deeper...\n";
return QProcess::execute(argv[0]);
}
Test run
./test
level 1<Enter>
level 1
We need to go deeper...
level 2<Enter>
and nothing going on...
PS. system() works, but will require to write code to correctly escape command line arguments.
Solved by using execvp() instead of QProcess::execute().
This code below is for executing ls -l | wc -l.
In the code, if I comment close(p[1]) in parent then the program just hangs, waiting for some input. Why it is so? The child writes output of ls on p1 and parent should have taken that output from p0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
main ()
{
int i;
int p[2];
pid_t ret;
pipe (p);
ret = fork ();
if (ret == 0)
{
close (1);
dup (p[1]);
close (p[0]);
execlp ("ls", "ls", "-l", (char *) 0);
}
if (ret > 0)
{
close (0);
dup (p[0]);
//Doubt, Commenting the line below does not work WHy?
close (p[1]);
wait (NULL);
execlp ("wc", "wc", "-l", (char *) 0);
}
}
pipe + fork creates 4 file descriptors, two are inputs
Before the fork you have a single pipe with one input and one output.
After the fork you will have a single pipe with two inputs and two outputs.
If you have two inputs for the pipe (that a proc writes to) and two outputs (that a proc reads from), you need to close the other input or the reader will also have a pipe input which never gets closed.
In your case the parent is the reader, and in addition to the output end of the pipe, it has an open other end, or input end, of the pipe that stuff could, in theory, be written to. As a result, the pipe never sends an eof, because when the child exits the pipe is still open due to the parent's unused fd.
So the parent deadlocks, waiting forever for it to write to itself.
Note that 'dup(p[1])' means you have two file descriptors pointing to the same file. It does not close p[1]; you should do that explicitly. Likewise with 'dup(p[0])'. Note that a file descriptor reading from a pipe only returns zero bytes (EOF) when there are no open write file descriptors for the pipe; until the last write descriptor is closed, the reading process will hang indefinitely. If you dup() the write end, there are two open file descriptors to the write end, and both must be closed before the reading process gets EOF.
You also do not need or want the wait() call in your code. If the ls listing is bigger than a pipe can hold, your processes will deadlock, with the child waiting for ls to complete and ls waiting for the child to get on with reading the data it has written.
When the redundant material is stripped out, the working code becomes:
#include <unistd.h>
int main(void)
{
int p[2];
pid_t ret;
pipe(p);
ret = fork();
if (ret == 0)
{
close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
execlp("ls", "ls", "-l", (char *) 0);
}
else if (ret > 0)
{
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execlp("wc", "wc", "-l", (char *) 0);
}
return(-1);
}
On Solaris 10, this compiles without warning with:
Black JL: gcc -Wall -Werror -Wmissing-prototypes -Wstrict-prototypes -o x x.c
Black JL: ./x
77
Black JL:
If the child doesn't close p[1], then that FD is open in two processes -- parent and child. The parent eventually closes it, but the child never does -- so the FD stays open. Therefore any reader of that FD (the child in this case) is going to wait forever just in case more writing it's gonna be done on it... it ain't, but the reader just doesn't KNOW!-)