I'm having problems with this simple loop exercise. I think the code is correct and I don't get any errors however when I run the program, I just get "^C" over and over again. Please help.
#import <readline/readline.h>
#import <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
printf("Where should I start counting? ");
const char *numInput = readline(NULL);
int countDownStart = atoi(numInput);
for (int i = countDownStart; i >= 0; i--) {
if (i % 3 == 0){
printf("%d\n", i);
if (i % 5 == 0) {
printf("Found one!\n");
}
}
}
return 0;
}
UPDATE 8/3/14
The code works when I enter the starting number using the numbers above my keyboard. However when I enter the starting number with my 10 key, I get "^C" every time I hit enter. Now I'm completely flummoxed but at least my code works.
Thank you for the help everyone. I understand atoi is not the best function to use but am trying to work through the Big Nerd Objective-C book.
Use strtol inplace of atoi as it returns error value in case of conversion failures.
You have to check the output received from function readline
const char *numInput = readline(NULL);
printf ("Input %s", numInput); //debugging
int countDownStart = atoi(numInput);
If the function is always returning the same string means, then the result also will remain the same.
Related
I just started learning computer science.
I'm studying through CS50 taught at Harvard online.
Well, I'm working on this one problem where I need to get the key from the user in command line,
then a plaintext, and then shift that text for key amount of numbers in ASCII to make a ciphertext.
here is what I've got so far.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar key\n");
}
{
string plaintext = get_string("plaintext: ");
int key = atoi(argv[1]);
int n = strlen(plaintext);
char chr[n];
printf("ciphertext: ");
for (int i = 0; i < n; i++)
{
chr[i] = plaintext[i];
if (isalpha(chr[i]))
{
if (isupper(chr[i]))
{
chr[i] = (chr[i] - 65 + key) % 26 + 65;
printf("%c",chr[i]);
}
else if (islower(chr[i]))
{
chr[i] = (chr[i] - 97 + key) % 26 + 97;
printf("%c",chr[i]);
}
}
else
{
printf("%c",chr[i]);
}
}
printf("\n");
}
}
well I know this seems very floppy but man it's my second week into programming while working full time.
anyways, I'm trying to have the user to run this program by using
./caesar "any number for the key".
if the user puts in any other things, then I'd like to print
"Usage: ./caesar key\n"
so far the only way i can think of is making the if statement with argc != 2
so that I can at least make sure the user puts in just one command on top of the program's name.
but the problem is that if the user puts in other things such as
./caesar HELLO
./caesar YolO
the program still runs.
I'm trying to figure out what I can do in order to prevent that from happening.
Really appreciate your time for reading this and help.
That is the reason way the old atoi function has been superseded by strtol. The former only try to convert an initial numeric part from the given string, while the latter also tells what remains after the converted part.
So to make sure that the user has given a number as sole argument, you could do:
int main(int argc, char *argv[]) {
long key;
int reject = 0;
if (argc != 2) { // ensure one argument
reject = 1;
}
else {
char *end;
key = strtol(argv[1], &end, 10); // ensure not empty and numeric
if ((*end != 0) || (end == argv[1])) reject = 1;
}
if (reject) {
printf("Usage: %s key\n", argv[0]);
return 1;
}
sscanf could be used too. It even allows blank characters after the number, which should not happen as the argv array is blank separated:
int main(int argc, char *argv[]) {
int key;
char empty[2];
if ((argc != 2) || (sscanf(argv[1], "%d%1s", &key, empty) != 1)) {
printf("Usage: %s key\n", argv[0]);
return 1;
}
...
To rephrase your question: You want to perform validation on user input, where the only legal input values are numeric strings: 123 and 4534 and 000 could all be considered valid, but hello world and f00 and one hundred thirty two are not valid.
In most programming languages, including C, strings are more or less just arrays of individual char elements (in other words, char is a primitive data type, but string is not.... C doesn't have a string data type at all. hint: take a look at the way you've declared main). So how can you use that to your advantage to validate the input to this program? Easy enough: every character in the input string must come from the domain [0123456789] (plus the null terminator \0 at the end...).
So to solve this problem, you just need to implement a check that verifies that the inputted value has that property. There are a number of ways to do that, maybe the easiest of which is:
int num;
int y = scanf("%d", &num);
then check the value of y. It will be set to the number of valid inputs that scanf read (so it will be 1 if a number was given).
Note: as mentioned in the comments, this will also accept things like 123abc (it will strip off the numbers and ignore the characters at the end). If you absolutely must have only numbers for input, scanf might not be the right function. In that case, using fgets to read the input as a string and then looping over each input to check that it is from the valid input domain might be a better approach.
The code I am working on needs a vector of doubles as an input and I was trying to make it variable sized, by using this small library I found on git. A first iteration using strings instead of doubles is:
printf("Write vector components (type 'stop' to stop): \n");
int stop = 0;
while (!stop)
{
fgets(c, sizeof(c), stdin);
if (strcmp("stop\n",c)!=0)
{
vector_add(&v, c);
} else {
stop = 1;
}
}
However, when I print the result (for example with 3 inputs and "stop") I get
the vector is:
stop
stop
stop
I have tried to write the first component everytime I input a new one, and the result is that the last one overwrites the first (and by extension, given the final result, every component).
However, this doesn't happen if I use vector_add manually. For example I have tried combining the example from git and my own code and the complete output is:
emil
hannes
lydia
olle
erik
stop
stop
stop
stop
So it only overwrites when reading. I can't even begin to comprehend what is happening. Haven't written any C in 2 years and I'm starting all over again.
Full code (not including vector library):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.c"
void main(int argc, char* argv[]) {
char c[20];
vector v; vector_init(&v);
printf("Write vector components (type 'stop' to stop):\n");
int stop = 0;
while (!stop)
{
fgets(c, sizeof(c), stdin);
if (strcmp("stop\n",c)!=0)
{
vector_add(&v, c);
// printf("%s\n", (char*)vector_get(&v, 0));
} else {
stop = 1;
}
}
printf("The vector is:\n");
for (int i = 0; i < vector_count(&v); i++) {
printf("%s\n", (char*)vector_get(&v, i));
}
} /* main */
vector_add doesn't copy the data, so your string is still stored in the variable c. When you read a new string, it overwrites the old one.
If your string library contains strdup, you can try this:
vector_add(&v, strdup(c));
First of all, I am talking about old-fashioned ANSI-C (I mean the ANSI standard and no C99 or newer) compiled with gcc. I am only allowed to use the libraries that can be seen below in the code.
My problem is I have a program that is called in the following way on the Terminal:
program < integer_1 integer_2
While I have been able to figure out how to check for the number of arguments, I'm stuck on checking if those are integers.
If the program is called like this:
program < 1 -13
it should run without complaining but if it is run like this:
program < s 7
it should throw out an error.
Whatever I have tried so far has been utter rubbish. The best thing I have managed so far has been an error message if the second number has been a character. None of my tries has been able to deal with more than one digit but I have figured out why that is.
The problem is that I haven't used command line / terminal arguments with any programming language i now (C++, Java). I would really appreciate it if someone could show me how check for correct input as frankly I am out of ideas.
Am I correct that if I want to deal with numbers bigger than 9, I have to iterate through argv starting from index 2 until I find a space?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int arc, char *argv[])
{
if(arc != 3)
{
printf("Error: You have entered %d arguments, but two were expected!", arc - 1);
return -1;
}
return 0;
}
The easiest way out is to iterate over the argv[n]s and pass one by one to them to strtol() or similar. Then, check for the error and make the decision. To quote the man page, (emphasis mine)
long int strtol(const char *nptr, char **endptr, int base);
[...]
If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
That said, program < integer_1 integer_2 is not exactly the way to pass the command-line arguments. If you want to pass the values arguments as command-line arguments, you shall lose the redirection operator and work with argc and argv[n]s directly..
Best way is to create a function for checking whether it is number or not.if the below function returns true then use atoi(argv[]) to convert them to integers to use it further.
bool isNumber(char number[])
{
int i = 0;
//checking for negative numbers
if (number[0] == '-')
i = 1;
for (; number[i] != 0; i++)
{
//if (number[i] > '9' || number[i] < '0')
if (!isdigit(number[i]))
return false;
}
return true;
}
Just a comment: not an answer
If you are going to use
program < arg1 arg2
You will not see arg1 or arg2 in the main parameters. arg1 is typically a filename or device which contain data which will be read by the program. I don't know if the program will even be able to access arg2. If you wish to pick up arg1 arg2 etc, lose the <
program arg1 arg2
You can try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int check_cmd_args(char const *str[], int numargs);
int
main(int argc, char const *argv[]) {
if (argc < 2) {
printf("Not enough command line arguements entered\n");
exit(EXIT_FAILURE);
}
if (check_cmd_args(argv, argc)) {
printf("All Command line arguements are integers\n");
} else {
printf("Error, non-integer command line arguement entered\n");
}
return 0;
}
int
check_cmd_args(char const *str[], int numargs) {
int n, i = 0;
for (n = 1; n < numargs; n++) {
if (str[n][0] == '-') {
i = 1;
}
for (; str[n][i]; i++) {
if (!isdigit(str[n][i])) {
return 0;
}
}
}
return 1;
}
I wrote a program that is supposed to solve this this problem. "Write a program that, given a string, a width, and an empty string for output, centers the string in the output area. Use a function that returns 1 if the formatting is successful and 0 if any errors, such as string is greater then length". My problem is that the my program just returns a lot of odd characters when it prints the string out. And it won't flag 0. What can I do to fix my code and or solve the problem better?
FULL CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int formatString(char str[250], char strcopy[250], int width);
int main()
{
char str[250];
char strcopy[250];
int width;
int outcome;
printf("Enter some text:\n");
gets(str);
printf("\nEnter a width (to check): ");
scanf("%d", &width);
printf("What you entered:");
printf("| %s |\n", str);
printf("\n");
outcome = formatString(str, strcopy, width);
if (outcome = 1)
{
printf("String copied.\n");
printf("| %s |", strcopy);
}
else
{
printf("Use a width val. that is the length of string\n");
}
return 0;
}
int formatString(char str[250], char strcopy[250], int width)
{
int sapceCheck;
int temp = 0;
sapceCheck = width - 1;
for (int i = 0; i < width; i++)
{
if (str[i] == '\0')
{
printf("Formating sucessful\n");
strncpy(str, strcopy, sizeof(str)-1); * (str + (sizeof(str) - 1)) = '\0';
temp = 1;
}
}
if (temp == 0)
{
return 0;
}
else
{
printf("Formating not sucessful\n");
printf("Width does not work\n");
return 0;
}
}
Don't miss the answer posted by 'Soravux', which contains all the right advice about how to fix the 'question' code.
Here is an alternate approach. However, the caller must ensure that the destination string 'strcpy' is large enough (length+1) to hold the output:
int formatString(char *str, char *strcopy, int length)
{
size_t strLength;
strLength = strlen(str);
/* Check if the string is greater than the length */
if(strLength > length)
return(0);
/* Print the centered 'str' to 'strcopy'. */
sprintf(strcopy, "%*s%*s",
(length+strLength) / 2, str, //leading spaces & 'str'
length - ((length+strLength) / 2), "" //trailing spaces
);
return(1);
}
A side note on your problem: returning 1 on success and 0 on failure is not the standard function behavior in C literature (aside from functions returning a boolean). Are you following a guide or a course?
You should not arbitrarily pre-allocate 250 chars for your strings. Strings are most often represented by char pointers, handled with dynamic memory allocation. I understand that gets() takes a pre-allocated buffer, but this is a really bad practice. You should consider using the fgets() function and use its maximum number of characters argument for a better security. Hard-coding string length is also hard to maintain (multiple places to modify the length) as well as confusing for readers (it's not clear if the compiler will pass the argument by copy or by reference).
Also, don't try to hide your code. The line containing the strncpy() have two statements, with the unary star pending in-between the two, looking like a multiplication operator. Don't do such things. Put the second statement on a new line.
That being said, you also misunderstood the arguments from the strncpy function: it is destination first, followed by source. You copy an uninitialized buffer (strcopy) into your string. Note that you also misinterpret the value of your temp variable which returns an error when something went well. It also returns 0 instead of 1 as asked.
Last notice: you really should break; your for-loop in your function formatString(), otherwise your strncpy will be executed for every \0 in your string.
I would recommend to check for exercises in a book if you are self-taught or seek the assistance of a TA if you are following a course. They will be able to guide you in the right path for understanding your mistakes.
I need to convert an array of number characters to integer values, in order to perform math operations in C. When I use atoi(argv[2][count]), it only converts the first digit to an integer. So if argv[2]=123, it only converts the '1' to an integer 1. How can I get '123' to be one integer value, 123? Thanks!
atoi is a good function to use, however you can write your own atoi function in C.
int xatoi(char *s)
{
int result=0;
while(*s)
{
result=result*10+(*s-48);
s++;
}
return result;
}
the logic behind this is every character '1','2',......'s ascii value is stored for example '1' has ASCII value '49'. please compile above program and check for errors i haven't tested it but i am sure it will work.
please see the link below for your reference
http://www.newebgroup.com/rod/newillusions/ascii.htm
argv is an array of string arrays and so argv[N] gives you an array. But argv[N][J] gives you element at position J of the array stored in argv[N]. However, it is strange that compiler did not complain about your code because atoi() function, in fact, expects a pointer (to the null-terminated string) and not a character value. The compiler should have said something like warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast. I recommend you not to ignore warnings. Personally I tend to compile the code with the highest warning level and not have a single warning, though our codebase at work is many millions of lines of code.
Also, prefer to use strtol over atoi. The problem with atoi is that it ignores invalid input (i.e. just returns you 0 if there is no problem, without affecting errno).
Anyway, here is an example of how to grab an array of base 10 integers from a command line:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
int n;
char *e;
int *v;
if (argc < 2) {
fprintf(stderr, "Please specify some numbers\n");
return EXIT_FAILURE;
}
n = argc - 1;
v = alloca(sizeof(int) * n);
for (i = 1; i < argc; ++i) {
v[i-1] = strtol(argv[i][i], &e, 10);
if (!v && errno) {
fprintf(stderr, "Cannot convert '%s' into number: %s\n",
argv[i], strerror(errno));
return EXIT_FAILURE;
} else if (*e != '\0') {
fprintf(stderr, "%s is not a number\n", argv[i]);
return EXIT_FAILURE;
}
}
printf("You have entered the following numbers: %d", v[0]);
for (i = 1; i < n; ++i)
printf(", %d", v[i]);
printf("\n");
return EXIT_SUCCESS;
}
Hope it is useful.