C program looping infinitely - scanf

I'm new here
and I'm also very new to programming
I'm trying to make a menu interface that loops back to the beginning after i input something
This is my code
#include <stdio.h>
#include <stdlib.h>
int x;
int main()
{MENU:
printf("Welcome to our menu\n");
printf("What do you want to do ?\nSelect your option\n\n");
printf("1. Binary to decimal converter\n");
printf("2. Lorem ipsum\n");
printf("3. Lorem ipsum\n");
printf("4. About us\n");
printf("5. Quit\n\n");
printf("Input your option:");
scanf("%d",&x);
printf("\n");
if (x==1){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==2){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==3){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==4){
printf("About us\n\n");
printf("Team Members");
goto MENU;
}
else if (x==5){
printf("Thank you for using this program");
exit(0);
}
else{
printf("Invalid input");
goto MENU;
}
}
The problem here now is that whenever I input something other than 1 to 5 the whole program will loop non-stop. Why is that ? What can I do about it ?

The OP is getting infinite loop when alphabetic character is entered. To avoid that you can get string input (maybe fgets) and check if all input characters are digit and then convert it to int using atoi etc.
Codewise you can do something like this:-
char numbuf[MAX_LEN];
int op,success=0;
while( fgets(numbuf,sizeof numbuf, stdin) ){
if(sscanf(numbuf, "%d",&op) == 1){
success=1;
break;
}else
fprintf(stderr,"%s","Error in input, give right one\n");
}
if( success )
// At this point you are sure that you have an int in `op`
success = 0;
Full code will be something like this:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100
int x;
int main()
{MENU:
printf("Welcome to our menu\n");
printf("What do you want to do ?\nSelect your option\n\n");
printf("1. Binary to decimal converter\n");
printf("2. Lorem ipsum\n");
printf("3. Lorem ipsum\n");
printf("4. About us\n");
printf("5. Quit\n\n");
printf("Input your option:");
char numbuf[MAX_LEN];
int success = 0;
while( fgets(numbuf,sizeof numbuf, stdin) ){
numbuf[strcspn(numbuf, "\n")] = 0;
if(sscanf(numbuf, "%d",&x) == 1){
success = 1;
break;
}
else
fprintf(stderr,"%s","Error in input, give right one\n");
}
if( success == 0){
exit(1);
}
success = 0;
if (x==1){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==2){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==3){
printf("This module doesn't exist yet\n\n");
goto MENU;
}
else if (x==4){
printf("About us\n\n");
printf("Team Members");
goto MENU;
}
else if (x==5){
printf("Thank you for using this program");
exit(0);
}
else{
printf("Invalid input");
goto MENU;
}
}
Still I don't understand why the infinite loop?
scanf consumes input if it matches format string. Here it doesn't.
So scanf stops consuming it. The non-matching input is still in the
input buffer. As a result, it is being skipped and you get the propmpt
frequently. You can also get rid of this by clearing the input buffer.
Use of goto is not something wrong but it generates code that is hard to maintain and debugging is much more difficult. We can use series of if else to simple switch-case statement that is much more clear to understand. Look at this code to notice these two things.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100
int main()
{
int x;
while(1){
printf("Welcome to our menu\n");
printf("What do you want to do ?\nSelect your option\n\n");
printf("1. Binary to decimal converter\n");
printf("2. Lorem ipsum\n");
printf("3. Lorem ipsum\n");
printf("4. About us\n");
printf("5. Quit\n\n");
printf("Input your option:");
char numbuf[MAX_LEN];
int success = 0;
while( fgets(numbuf,sizeof numbuf, stdin) ){
numbuf[strcspn(numbuf, "\n")] = 0;
if(sscanf(numbuf, "%d",&x) == 1){
success = 1;
break;
}
else
fprintf(stderr,"%s","Error in input, give right one\n");
}
if( success == 0){
exit(1);
}
success = 0;
switch(x){
case 1:
case 2:
case 3: printf("This module doesn't exist yet\n\n");
continue;
case 4: printf("About us\n\nTeam Members");
continue;
case 5: printf("Thank you for using this program");
exit(0);
default:printf("Invalid input");
}
}
return 0;
}
Jokes apart:

You can make it simpler by making use of a do while loop and switch case in it.
Try this
int main()
{
int x;
do
{
printf("Welcome to our menu\n");
printf("What do you want to do ?\nSelect your option\n\n");
printf("1. Binary to decimal converter\n");
printf("2. Lorem ipsum\n");
printf("3. Lorem ipsum\n");
printf("4. About us\n");
printf("5. Quit\n\n");
printf("Input your option:");
scanf("%d",&x);
printf("\n");
//Switch statement
switch(x)
{
case 1: printf("This module doesn't exist yet\n\n");
break;
case 2: printf("This module doesn't exist yet\n\n");
break;
case 3: printf("This module doesn't exist yet\n\n");
break;
case 4: printf("About us\n\n");
printf("Team Members");
break;
case 5: return 0;
default: printf("Invalid input");
}
}while(1);
}

Related

getchar(), putchar(char), EOF

#include<stdio.h>
int main(){
int c = getchar();
while(c != EOF){
putchar(c);
c = getchar();
}
}
In above code why does not the program terminates by itself after c becomes EOF?
Reference of the code > Book: K&R's The C Programming Language 2nd Edition,
Page: 18
getchar() will return EOF only if the end of file is reached. The ‘file’ here is the standard input itself.
This can be written as:
#include <stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF)
{
/*getchar() returns the the next available value which is in the input
buffer*/
putchar(c);
}
}

C++ class member variable resetting to 0

I'm trying to increment and decrement the index of a list of readings, however, everytime I run update(), m_notifIndex gets set back to zero. I'm sorry if this type of question has been asked before, but after looking for the answer for an hour, I gave up and went on to ask my first question here. Sorry for the bad formatting too, again, this is my first time posting.
Display.cpp
#include "display.h"
#include <time.h>
#include <unistd.h>
#include <iostream>
Display::Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages) {
m_notifIndex = 0;
}
void Display::update() {
if (m_showNotif) {
//when there are no more messages, show the notifications
while (!m_notifications->isEmpty()) {
//first draw the notification if there is a warning in the current index
if (m_notifications->sensors[m_notifIndex] != NULL) {
m_oled->clear(PAGE);
drawSensor();
m_oled->display();
sleep(1);
//keep updating the message and notif stack when there are no inputs
while (m_a->pinRead() == HIGH && m_right->pinRead() == HIGH && m_left->pinRead() == HIGH && m_b->pinRead() == HIGH) {
m_messages->updateMsgStack();
updateNotif();
if (!m_messages->isEmpty() || m_notifications->warnings[m_notifIndex])
return; //break away from the loop if a new message comes in
}
//listen in for inputs
if (m_right->pinRead() == LOW) {
//wait until the button is released
while (m_right->pinRead() == LOW) {}
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
else if (m_left->pinRead() == LOW) {
while (m_left->pinRead() == LOW) {}
if (m_notifIndex == 0)
m_notifIndex = m_num_sensors-1; //wrap around when at the beginning
else m_notifIndex--;
}
else if (m_a->pinRead() == LOW) {
while (m_a->pinRead() == LOW) {}
m_showNotif = false;
return;
}
checkForPanic();
}
else { //when the current index has no warning
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
}
}
}
void Display::updateNotif() {
std::string line;
for (unsigned int i = 0; i < sizeof(m_sensors)/sizeof(m_sensors[0]); i++) {
const char* filePath = (m_notifDir + m_sensors[i] + ".txt").c_str();
if (m_messages->exists(filePath)) {
usleep(10000);
try {
m_messages->m_incMsg.open(filePath);
while(std::getline(m_messages->m_incMsg, line)) {
m_notifications->addWarning (line, i);
}
m_messages->m_incMsg.close();
}
catch (std::ios_base::failure& e) {
std::cerr << e.what() << '\n' << std::endl;
}
}
else m_notifications->removeWarning (i); //delete the warning when the file doesnt exist
}
}
void Display::checkForPanic() {
if (m_b->pinRead() == LOW) {
time_t hold;
time(&hold);
while (m_b->pinRead() == LOW) {
if (time(NULL) > hold + 3) { //if the timer reaches 3 seconds
//m_messages->sendReply("Miner_Emergency");
return;
}
}
}
}
Display.h
#ifndef OLED_DISPLAY_H_
#define OLED_DISPLAY_H_
#include <sstream>
#include <string>
#include "image/image.h"
#include "oled/Edison_OLED.h"
#include "message.h"
#include "DataStructs/Notif.h"
#include "gpio/gpio.h"
#define SLEEPTIMEOUT 20
class Display {
public:
Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages);
void run();
~Display();
private:
edOLED* m_oled;
const unsigned int m_height, m_width;
Image* m_miner;
Image* m_checkin;
Image* m_reminder;
Image* m_blast;
Image* m_go_to;
Image* m_goto_zone;
bool m_isSleeping, m_showNotif;
time_t m_timer;
Message* m_messages;
std::string* m_sensors;
std::string m_notifDir;
NotifHandler* m_notifications;
unsigned int m_notifIndex;
const unsigned int m_num_sensors;
gpio* m_up;
gpio* m_down;
gpio* m_left;
gpio* m_right;
gpio* m_a;
gpio* m_b;
void drawImage(Image* image);
void update();
void drawMessage(MsgNode* message);
void drawTime();
void drawSensor();
void updateNotif();
void checkForPanic();
};
#endif //OLED_DISPLAY_H_

Parsing /proc psinfo and argv returns: Value too large for defined data type error

I have a fairly simple code below for processing /proc/* files in solaris to obtain process information and arguments. For the most part it works (meaning it does present arguments correctly on some processes), but on some process arguments (particularly where they are long), it fails and produces the error Value too large for defined data type
Does anyone have any idea perhaps why it fails?
It is the pread() line for the arguments array that fails at line 108.
It is actually some java processes with many arguments where it fails if that helps.
What's interesting too is that:
examining the binary /proc/<pid>/psinfo file, it is very small--the size is clearly not sufficient to contain the kind of long arguments that I am looking at with some processes. Doing hex dump of the contents of the psinfo file confirms that they are not there.
the value of pr_argv when there are long arguments is zero.
On further digging, it looks like the arguments are in /proc/(pid)/object/tmpfs.394.2.71404854. I wonder why.
Code:
#include <dirent.h>
#include <ctype.h>
#include <assert.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/processor.h>
#include <sys/sysinfo.h>
#include <sys/param.h>
#include <kstat.h>
#include <procfs.h>
#define PROC_ERRNO ((errno == ENOENT) ? ESRCH : errno)
#define my_pread(fd, ptr, type, offset) \
(pread(fd, ptr, sizeof(type), offset) == sizeof(type))
static int proc_psinfo_get(psinfo_t *psinfo, pid_t pid)
{
int fd, retval = 0;
char buffer[BUFSIZ];
sprintf(buffer, "/proc/%d/psinfo", pid);
if ((fd = open(buffer, O_RDONLY)) < 0) {
return ESRCH;
}
if (!my_pread(fd, psinfo, psinfo_t, 0)) {
retval = errno;
}
close(fd);
return retval;
}
int main(int argc, char **argv)
{
DIR *dirp = opendir("/proc");
struct dirent *ent;
char *models[] = {
"unknown", "32bit", "64bit"
};
while ((ent = readdir(dirp))) {
pid_t pid;
psinfo_t psinfo;
int retval;
char buffer[BUFSIZ];
char *argvb[56];
char **argvp = argvb;
int n, fd;
size_t nread = 0;
unsigned int argv_size;
if (!isdigit(*ent->d_name)) {
continue;
}
psinfo.pr_dmodel = 0;
pid = strtoul(ent->d_name, NULL, 10);
retval = proc_psinfo_get(&psinfo, pid);
printf("---------------------------------\n");
printf("pid=%d, status=%s, model=%s\n",
pid, retval ? strerror(retval) : "OK",
models[psinfo.pr_dmodel]);
printf("Parent Pid: %ld\n", psinfo.pr_ppid);
printf("UID: %ld\n", psinfo.pr_uid);
printf("size: %ld\n", psinfo.pr_size);
printf("rss: %ld\n", psinfo.pr_rssize);
printf("pcpu: %d\n", psinfo.pr_pctcpu);
printf("pctmem: %d\n", psinfo.pr_pctmem);
printf("zoneid: %d\n", psinfo.pr_zoneid);
printf("pr_sname: %c\n", psinfo.pr_lwp.pr_sname);
printf("Up Start: (%ld, %ld)\n", psinfo.pr_start.tv_sec, psinfo.pr_start.tv_nsec);
printf("Command: %s\n", psinfo.pr_fname);
// print argc
argv_size = sizeof(*argvp) * psinfo.pr_argc;
sprintf(buffer, "/proc/%d/as", pid);
printf("argc=%d, argv_size=%d\n",
psinfo.pr_argc, argv_size);
if ((fd = open(buffer, O_RDONLY)) < 0) {
printf("open(%s) == %s\n",
buffer, strerror(PROC_ERRNO));
if (argvp != argvb) {
free(argvp);
}
continue;
}
if (argv_size > sizeof(argvb)) {
argvp = malloc(argv_size);
}
if ((long int)(nread = pread(fd, argvp, argv_size, (off_t)psinfo.pr_argv)) <= 0) {
close(fd);
printf("error in reading argvp\n");
printf(" pread(%d, 0x%lx, %d, 0x%lx) == %d (%s)\n",
fd, (unsigned long)argvp, argv_size,
(unsigned long)psinfo.pr_argv,
nread, strerror(errno));
continue;
}
// parse the args here
for (n = 0; n < psinfo.pr_argc; n++) {
int alen;
char *arg;
if ((long int)(nread = pread(fd, buffer, sizeof(buffer), (off_t)argvp[n])) <= 0) {
close(fd);
printf("buffer %d argvp as ld %ld argvp as lu %lu ", sizeof(buffer), argvp[n] , argvp[n] );
printf(" %-2d) pread(%d, 0x%lx, %d, 0x%lx) == %d (%s)\n",
n, fd, (unsigned long)&buffer[0], sizeof(buffer),
(unsigned long)argvp[n],
nread, strerror(errno));
break;
}
printf(" %-2d) nread=%-4d, ", n, nread);
fflush(stdout);
alen = strlen(buffer)+1;
printf(" alen=%-4d ", alen);
fflush(stdout);
arg = malloc(alen);
memcpy(arg, buffer, alen);
printf(" {%s}\n", arg);
fflush(stdout);
}
if (argvp != argvb) {
free(argvp);
}
close(fd);
}
closedir(dirp);
return 0;
}
You're trying to read from a starting position past the end of the file.
From the pread man page:
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
...
EOVERFLOW
The file is a regular file, nbyte is greater than 0, the starting
position is before the end-of-file, and the starting position is
greater than or equal to the offset maximum established in the open
file description associated with fildes.

Error in use of the pcap_findalldevs_ex Function in c++

Below this program to retrieve the list of adapters and print it on the screen :
#include <stdio.h>
#include <pcap.h>
int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs_ex: %s/n", errbuf);
exit(1);
}
for(d= alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)/n", d->description);
else
printf(" (No description available)/n");
}
if (i == 0)
{
printf("/nNo interfaces found! Make sure WinPcap is installed./n");
return 0;
}
pcap_freealldevs(alldevs);
}
It is compile But Give an Error :
Every body have These Errors, while using pcap.h, go to bellow link and download pcap, after it Install it :
http://www.winpcap.org/install/default.htm

not /n in scanf but program still waits

I've read on here that the /n in scanf makes the program wait for another input. my program however does not have a /n in scanf but it still waits for another input after i enter a number. Not sure why.
#include <stdio.h>
int main()
{
int inputNumber, index = 2, lowestPrime = 1, number = 1;
printf("Enter an integer: ");
scanf("%d", &inputNumber);
if(scanf("%d", &inputNumber) != 1)
{
printf("Invalid input");
return 1;
}
else
{
printf(" The prime factorization of %d is",inputNumber);
while(inputNumber > lowestPrime)
{
if(inputNumber % index != 0)
{
index += 1;
}
else
{
inputNumber = (inputNumber / index);
printf(" %d", index);
}
}
}
return 0;
}
You're calling scanf twice here, once for the original call and once in your if statement. Replace the statement inside the if parenthesis by
if (inputNumber!= 1)
and you should be fine!