I am trying to input string into fixed size char array.
I have a questions:
when I input a string which is bigger than the char array, the array become bigger without any additional declaration. I want to make the code only take the string that 'equal or smaller than the char array'.
Thank You.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
/***************************Function****************************/
int string_length(char s[]) {
int c = 0;
while (s[c] != '\0')
c++;
return c;
}
/**************************************************************/
char *str;
int arrSize;
void opt1()
{
printf("Enter array size: ");
scanf("%d", &arrSize);
arrSize=arrSize+1;
str = malloc(arrSize);
return;
}
void opt2()
{
printf("Enter characters: ");
scanf("%s", str);
length = string_length(str);
printf("your input is '%s'\n", str);
printf("your input length is '%d'\n", length);
return;
}
int main()
{
int input = 0;
while(input != 3) {
printf("\n NAME \n");
printf("\n");
printf("--------------------------------------\n");
printf("1) Making Array \n");
printf("2) Check Array \n");
printf("3) Quit\n");
printf("\nEnter selection: ");
scanf("%d", &input);
if( input == 1 ) {
/* */
opt1();
}
else if(input == 2) {
opt2();
}
}
return 1;
}
OP wants to read data, yet if larger that the target array, then do not change the target array.
// 1: success
// -1 EOF
// 0: Input too long
int read_array(char *buffer, size_t size) {
char tmp[size];
size_t i = 0;
int ch;
while ((ch = fgetc(stdin)) != EOF && ch != '\n') {
if (i < size) {
tmp[i++] = ch;
}
}
if (ch == EOF && i == 0) return EOF;
if (i >= size) return 0; // too many
memcpy(buffer, tmp, i);
buffer[i] = '\0';
return 1;
}
Normally code could use fgets(), but there are corner cases that fail to meet OP goals.
To read in a whole line, you can use fgets:
char line[80];
if (fgets(line, sizeof line, stdin) != NULL) {
// use the input
}
Now you won't need to check if the user entered more than the limit, since fgets will only get the first 79 (-1 for null terminator) characters; the remainder, if any, will be ignored.
Related
After i put a name in the terminal and it is shorter, then 20 chars, it wants inputs until i have filled all the 20 positions in the array.
I know it is because of the for cycle i have there, but I don't know how else to fill that end of the array with nothing("").
In the array there is for example this "Helloworld\n123\n123"
Thank you for help in advance.
#define NAME 20
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
main(void) {
char name[NAME] = {""};
malloc(sizeof(name[NAME]));
printf("Choose your name: ");
for (int i = 0; i < NAME; i++) {
scanf("%c", &name[i]);
}
//Welcome and the name
printf("Welcome: ");
for (int i = 0; i < NAME; i++) {
printf("%c", name[i]);
}
return 0;
}
You need to stop reading at a newline (+should also check return codes).
A loop like:
size_t i=0;
for (; i < sizeof(name)-1; i++) {
if (1==(scanf("%c",&name[i]))){ if (name[i]=='\n') break; }
else if (feof(stdin)) break; //end of file?
else return perror("getchar"),1; //report error
}
name[i]='\0';
will achieve that (can also use getchar/getc/fgetc instead of scanf)
or you can use fgets:
if(NULL==fgets(name,sizeof(name),stdin)) return perror("fgets"),1;
//erase a possibly included newline at the end
//(won't be there if you pressed Ctrl+D twice rather than
//Enter to submit your input or if you're at the end of
//a stdin redirected from a file)
size_t len = strlen(name);
if(name[len-1]=='\n') name[len-1]='\0';
Whole program with both versions (in the if(0){...}else{...}) :
#define NAME 20
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main(void) {
char name[NAME] = {""};
//malloc(sizeof(name[NAME])); //a useless memory leak; don't do this!
printf("Choose your name: ");
if(0){
if(NULL==fgets(name,sizeof(name),stdin)) return perror("fgets"),1;
size_t len = strlen(name);
if(name[len-1]=='\n') name[len-1]='\0';
}else{
size_t i=0;
for (; i < sizeof(name)-1; i++) {
if (1==(scanf("%c",&name[i]))){ if (name[i]=='\n') break; }
else if (feof(stdin)) break; //end of file?
else return perror("getchar"),1;
}
name[i]='\0';
}
//Welcome and the name
printf("Welcome: ");
for (int i = 0; i < NAME; i++) {
printf("%c", name[i]);
}
return 0;
}
If you have to use scanf and %c format:
char *readLineUsingCharAndScanf(char *buff, size_t size, FILE *fi)
{
char ch;
char *wrk = buff;
while(size-- && fscanf(fi, "%c", &ch) == 1 && ch != '\n' ) *wrk++ = ch;
*wrk = 0;
return buff;
}
void dumpString(const char *restrict str, size_t size)
{
while(*str && size--)
{
printf("%03d [0x%02x] - %s\n", *str, *str, (*str >= 32 & *str <= 127) ? (char[]){'\'', *str, '\'', 0} : "not printable");
str++;
}
}
int main(void)
{
char name[20];
dumpString(readLineUsingCharAndScanf(name, 19, stdin), 20);
}
https://godbolt.org/z/vWvP68TbW
scanf() is not the best tool for your purpose. Here is a simple and safe solution:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define NAME 20
int main(void) {
char name[NAME];
int c;
size_t i;
printf("Enter your name: ");
i = 0;
while ((c = getchar()) != EOF && c != '\n') {
if (i < sizeof(name) - 1)
name[i++] = c;
}
name[i] = '\0';
//Welcome and the name
printf("Welcome: %s\n", name);
return 0;
}
If you must use scanf(), use this:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define NAME 20
int main(void) {
char name[NAME];
char c;
size_t i;
printf("Enter your name: ");
i = 0;
while (scanf("%c", &c) == 1 && c != '\n') {
if (i < sizeof(name) - 1)
name[i++] = c;
}
name[i] = '\0';
//Welcome and the name
printf("Welcome: %s\n", name);
return 0;
}
Thank you everyone for answering. Unfortunately the first two answers are too complicated for me yet. And the third one was not working properly.
But I found the simplest answer. :) Many thanks
#include <stdio.h>
int main(void)
{
char name[20];
printf("Choose your name: ");
scanf("%[^\n]*c",name);
printf("My name is %s",name);
}
For your needs I would use scanf with the string conversion specifier %s. In this case, the input name would be read and stored character by character in the buffer until the whitespace would be read. Here is the code.
#define NAME 20
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char name[NAME] = {""};
malloc(sizeof(name[NAME]));
printf("Choose your name: ");
scanf("%s", &name);
printf("%s", &name);
return 0;
}
What I mean by this is, I'm writing a program where the user inputs a string along with a '*' character and any number, and the program multiplies the string the user entered by that number
Please enter a string you'd like multiplied: horse*3
output:
horsehorsehorse
What I'd like to do is, if that string happens to be a number, then multiply the two numbers like you normally would
Please enter a string you'd like multiplied: 2*2
output:
4
I'm putting my code down below.
int multStr(char *strMult) //strMult is character array for initial input
{
//printf("\nRedirected to here!\n");
printf("Please enter a string and number you'd like to multiply by: ");
scanf(" %[^\n]s", strMult); //User scans in the string intended for multiplication
char string[255]; //Character array for the string part
char number[255]; //Character array for the number the string is to be multiplied by
int counter=0;
int i;
for(i=0;strMult[i] != '*'; i++)
{
string[i] = strMult[i];
counter++;
}
if(string[i] >= '0' && string[i] <= '9')
{
int strNum = myAtoi(string);
printf("String: %d", strNum);
}
else
{
printf("String: %s\n", string);
}
counter++;
for(i=0; strMult[counter] != '\0'; counter++, i++)
{
number[i] = strMult[counter];
}
//number[i+1] = '\0';
printf("Number: %s\n", number);
int num = myAtoi(number);
//printf("Number after convert: %d\n", num);
for(i=0; i<num; i++)
{
printf("%s", string);
}
printf("\n");
return(0);
}
strMult is a char array I called from main. I was not able to use stdlib, so I created my own Atoi function
You have a couple issues here. The first thing you're doing is splitting the string into two char[]s string and number. You seem to do that ok. The next thing you need to do is to check that string is a number.
if(string[i] >= '0' && string[i] <= '9')
{
int strNum = myAtoi(string);
printf("String: %d", strNum);
}
else
{
printf("String: %s\n", string);
}
This is what you're using, but note that it has no consequence to the rest of the program. Your number is local to the if block, and then it goes away, so you cannot use it later. What you want to do, is make the number available later.
int isNumber = 1;
int strNum;
for(int k = 0; k < i; k++){
if( string[k] >= '0' && string[k]<='9' ){
//continue checking
}else{
isNumber=0;
}
}
if (isNumber==1){
strNum = myAtoi(string);
} else{
// print your string or some such.
}
Note that I check all of the characters in the string, and not just the '*' which is the character at the i'th position. That way, if somebody enters horse42*2, it will think it is a string.
Also, you can improve this by checking the values as you separate out the number.
Regular expressions are a useful tool for parsing user input. Reading unconstrained user input with scanf is dangerous because unexpectedly long input will overflow the buffer.
Here is an example that use getline for reading input safely and regular expressions to sort out the format for the user input.
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#define TERM "(([[:digit:]]+)|([[:alpha:]]+))"
void string_by_number(int number, char *string)
{
printf("number %d string %s\n", number, string);
for (int i = 0; i < number; ++i) {
printf("%s", string);
}
printf("\n");
}
int main(int argc, char *argv[])
{
regex_t re;
regmatch_t capture[7];
if (regcomp(&re, TERM "[[:space:]]*[*][[:space:]]*" TERM, REG_EXTENDED)) {
fprintf(stderr, "error in regular expression pattern\n");
return 1;
}
char *line = NULL;
size_t line_size = 0;
printf("Please enter a string you'd like multiplied: ");
while (0 < getline(&line, &line_size, stdin)) {
if (regexec(&re, line, 7, capture, 0)) {
printf("Unexpected input '%s'\n", line);
continue;
}
int format = 0;
char *lhs_string = NULL;
int lhs_number;
char *rhs_string = NULL;
int rhs_number;
if (capture[2].rm_so >= 0) {
format ^= 0x01;
lhs_number = strtol(&line[capture[2].rm_so], NULL, 10);
}
else {
lhs_string = &line[capture[3].rm_so];
line[capture[3].rm_eo] = '\0';
}
if (capture[5].rm_so >= 0) {
format ^= 0x02;
rhs_number = strtol(&line[capture[5].rm_so], NULL, 10);
}
else {
rhs_string = &line[capture[6].rm_so];
line[capture[6].rm_eo] = '\0';
}
switch (format) {
case 0x00: printf("Can't do 'string' * 'string'\n"); break;
case 0x01: string_by_number(lhs_number, rhs_string); break;
case 0x02: string_by_number(rhs_number, lhs_string); break;
case 0x03: printf("%d\n", lhs_number * rhs_number); break;
}
printf("\nPlease enter a string you'd like multiplied: ");
}
free(line);
regfree(&re);
return 0;
}
Hi I know that there are alot of examples where you input a character to and output the position of the character. But how do you do it the other way around where you input the position and output the character ?
input string: abcdefghijklmnopqrstuvwxyz
input position: 0
output: The character in position 0 is 'a'
Do I use atoi?
int main(void) {
char line[SIZE];
int position;
// int character = getchar(); //get string
scanf("%d\n", &position); //get position
int i = 0;
while(fgets(line, SIZE, stdin) != NULL) {
if(line[i] == position) {
printf("The character in postion %d is '%c'\n", position,line[i]);
//flag = TRUE;
// }
i++;
}
return 0;
}
while(fgets(line, SIZE, stdin) != NULL)
{
line[strlen(line)-1] = '\0'; // as fgets append '\n' before '\0', replacing '\n' with '\0'
if(strlen(line) > position)
{
printf("The character in postion %d is '%c'\n", position,line[position]);
}
else
{
printf("invalid position\n");
}
}
You probably want this:
#include <stdio.h>
#define SIZE 100
int main(void) {
char line[SIZE];
int position;
scanf("%d", &position); //get position
getchar(); // absorb \n from scanf (yes scanf is somewhat odd)
while (fgets(line, SIZE, stdin) != NULL) {
printf("The character in postion %d is '%c'\n", position, line[position]);
}
return 0;
}
No out of range check whatsoever is done here for brevity
Example of execution:
1
abc
The character in postion 1 is 'b'
Hello
The character in postion 1 is 'e'
TEST
The character in postion 1 is 'E'
This small example may help too:
#include <stdio.h>
#define SIZE 100
int main(void) {
char line[SIZE];
fgets(line, SIZE, stdin);
for (int i = 0; line[i] != 0; i++)
{
printf("The character in postion %d is '%c'\n", i, line[i]);
}
}
No error checks done either for brevity.
int n;
int a[maxsize];
int b[maxsize];
int c[maxsize];
int i;
printf("enter number of elements(disks)\n");
scanf("%d",&n);
printf("enter the elements in ascending order\n");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
This works fine at times, but most of the times this piece of code is going into infinite loop,the 'scanf' in the loop is accepting values infinitely,i tried using the function (fflush) to clear the buffer contents,but still its not working, someone please help me out!! and please explain why !!
The code posted cannot enter an infinite loop, it's probable that the scanf() function is blocking until you input something like a Ctrl+D to end the input stream or maybe another integer, the problem is that you are handling the input in a very dangerous way because you are not checking for errors at all, what might do what you exactly want is this
#include <stdio.h>
#include <stdlib.h>
#define clearstdin() do {int chr; while (((chr = getchar()) != EOF) && (chr != '\n')); } while (0)
#define SOMELARGESIZE 1024
int main(void)
{
unsigned int index;
unsigned int size;
int result;
fprintf(stderr, "input the desired array size: ");
while (((result = scanf("%u", &size)) != 1) && (result != EOF))
{
fprintf(stderr, "invalid input, try again\n");
clearstdin();
}
if (result == EOF)
{
fprintf(stderr, "EOF recieved, ending the program\n");
return -1;
}
if (size < SOMELARGESIZE)
{
int array[size];
for (index = 0 ; index < size ; index++)
{
fprintf(stderr, "input an integer: ");
if (((result = scanf("%d", &array[index])) == 1) && (result != EOF))
fprintf(stdout, "\tarray[%d] = %d\n", index, array[index]);
else if (result == EOF)
{
fprintf(stderr, "EOF recieved, ending the program\n");
return -1;
}
else
{
fprintf(stderr, "invalid input, try again\n");
index -= 1;
}
clearstdin();
}
}
else
{
fprintf(stderr, "sorry, you requested a very large array\n");
return -1;
}
return 0;
}
the only problem with the program above, is that if you input any white space character while scanf() is wating for input it will do nothing, until valid or invalid input but specifically non-white-space input is entered.
scanf will return the number of items successfully scanned.
If scanf does not return 1, a character is read and scanf tries again.
scanf ( "%*[^0-9\n]"); will read and discard any characters that are NOT numbers or a newline.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int i;
int n;
int a[SIZE];
printf("enter number of elements(disks) 0-%d\n", SIZE - 1);
while ( scanf("%d",&n) != 1 || n >= SIZE) {
scanf ( "%*[^0-9\n]");
printf ( "problem with input, try again\n");
}
printf("number was %d\n", n);
printf("enter the elements in ascending order\n");
for(i=0;i<n;i++)
{
while ( scanf("%d",&a[i]) != 1) {
scanf ( "%*[^-0-9\n]");//[^-0-9\n] characters NOT digit, newline or minus
printf ( "problem with input, try again\n");
}
printf("number for a[%d] was %d\n", i, a[i]);
}
return 0;
}
I am absolutely brand new at programming and im not sure how to explain what im doing here.
The whole purpose of this piece is to enter values and then print them out in the same order. Now I wanna quit from entering values when pressing 'q' and so I have to scanf for chars but when I assign them back to the int array the values are not the same.
Hope that makes any sense to you but in any case heres my code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5000
define flush fflush(stdin)
main() {
int input[SIZE] = {0},i = 0;
int counter = 0;
char inputs, quit;
do {
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
flush;
scanf("%c",&inputs);
flush;
if (inputs == 'q')
quit = 'q';
else {
input[i] = inputs;
counter++;
i++;
}
} while (i < SIZE && quit != 'q');
for(i = 0; i < counter; i++){
printf("%i.%i\n", i + 1, input[i]);
}
system("pause");
}
Ive been trying to do this on my own btw and also researched some information online regarding chars but couldnt find anything that would help me. Thanks a lot in advance.
You should nor be getting integer through %c neither assign char values to integers variables when that is not the intention, rather you should approach something like this
i = 0;
do {
printf("Enter a number: ");
scanf("%d", &input[i]);
i++; counter++;
printf("Do you want to continue? (y/n) : ");
scanf("%c", &inputs);
} while(inputs == 'y');
or u can get the number of integer inputs upfront and loop to get that much integers.
try instead (using your original code as much as possible):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 5000
int main()
{
int input[SIZE] = {0},i = 0;
int counter = 0;
char inputs[32];
bool quite = false;
do
{
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
// read a string from user, then convert when appropr
fgets(stdin, sizeof(inputs), inputs);
if (inputs[0] == 'q')
{
quit = true;
}
else if ( isdigit(inputs[0]) )
{
input[i] = atoi(inputs); // this will disregard any ending \n
counter++;
i++;
}
}
while (i < SIZE && !quit);
for(i = 0; i < counter; i++)
{
printf("%i.%i\n", i + 1, input[i]);
}
system("pause");
}
Another variant. This one will read in characters regardless of the use of whitespaces, since it uses getchar() rather than scanf(). I'm not sure if this is what you want. It seems as though you want integers but are reading characters. So this solution may be completely off base.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5000
int main()
{
char input[SIZE] = {0};
int i = 0;
int counter = 0;
char inputs;
printf("Input number ('q' to quit and display numbers entered): ");
while (((inputs = getchar()) != EOF) && (counter < SIZE))
{
if (inputs == 'q')
break;
input[counter] = inputs;
counter++;
}
for(i = 0; i < counter; i++)
{
printf("%c\n", input[i]);
}
system("pause");
return 0;
}
If you do really want ints, this one should work.
Notice that the atoi() function can be used to convert a C-string to an int.
The fgets() function is used to read the C-string from STDIN. However, scanf("%s", input); would also work here, as opposed to the scanf("%c", &inputs); that you used.
#include <stdio.h>
#include <stdlib.h>
#define INPUT_SIZE 1000
#define SIZE 5000
int main()
{
char input[INPUT_SIZE] = {0};
int numbers[SIZE] = {0};
int i = 0;
int counter = 0;
while ((fgets(input, sizeof(input), stdin) != NULL) && (counter < SIZE))
{
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
if (input[0] == 'q')
break;
numbers[counter] = atoi(input);
counter++;
}
for(i = 0; i < counter; i++)
{
printf("%i\n", numbers[i]);
}
system("pause");
return 0;
}