Program:
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
//#include "iostream"
const int IDLEN = 10;
const int POLARITYLEN = 3;
const int MAXSTOCKITEMS = 10;
struct TransistorRec {
char manufacturersID[IDLEN + 1];
char polarity[POLARITYLEN + 1];
float power;
float gain;
int stock;
};
typedef struct TransistorRec Transistor;
struct StockRec{
int size;
Transistor stocklist[MAXSTOCKITEMS];
};
typedef struct StockRec Stock;
int main()
{
int total, i;
struct TransistorRec a[10];
char x, y;
printf("How many transistors: ");
scanf_s("%i", &total);
if (total >MAXSTOCKITEMS){
printf("too much!! repeat");
scanf_s("%i\n", &total);
}
for (i = 0; i < total; i++)
{
printf("Enter manufacturer's ID of transistor:");
scanf_s("%s",a[i].manufacturersID);
printf("Enter polarity of transistor: ");
scanf_s("%s",a[i].polarity);
printf("Enter power of transistor: ");
scanf_s("%f",a[i].power);
printf("Enter gain of transistor: ");
scanf_s("%f",a[i].gain);
printf("Enter current stock of transistor: ");
scanf_s("%i",a[i].stock);
}
return 0;
}
My assignment:
Write a C function that reads from the user (keyboard) the information about the transistors in stock,
and stores this information in the Stock structure. A sample set of input data (manufacturer’s ID,
polarity, maximum power, current gain, number in stock) is:
2N2222 NPN 0.5 75 23
BC559 PNP 0.5 125 7
TIP31B NPN 40.0 20 11
Problem:
When i input my values(strings) through scanf_s to a structure , the program will stop.
Quoting from the documentation of scanf_s,
Remarks:
[...]
Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable.
So, the scanf_ss:
scanf_s("%s",a[i].manufacturersID);
scanf_s("%s",a[i].polarity);
need a third argument specifing the buffer size as mentioned in the above quote. So, use
scanf_s("%s",a[i].manufacturersID,sizeof(a[i].manufacturersID));
scanf_s("%s",a[i].polarity,sizeof(a[i].polarity));
or
scanf_s("%s",a[i].manufacturersID,_countof(a[i].manufacturersID));
scanf_s("%s",a[i].polarity,_countof(a[i].polarity));
There are other errors too. These:
scanf_s("%f",a[i].power);
scanf_s("%f",a[i].gain);
scanf_s("%i",a[i].stock);
needs to be
scanf_s("%f",&a[i].power);
scanf_s("%f",&a[i].gain);
scanf_s("%i",&a[i].stock);
as the %f and %i expects a float* and int* respectively, and not a float and int.
As for why the first two scanf_s did not require a &, because ,in C, array names "decay" to a pointer to its first element. a[i].manufacturersID and a[i].polarity are arrays and the "decay" automatically happens.
You should also remove the \n from
scanf_s("%i\n", &total);
because \n is considered as a whitespace character and this character will discard any number of whitespace characters including none until the first non-whitespace character as specified in the C11 standard:
7.21.6.2 The fscanf function
[...]
A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.
Related
I'm trying to reference global variables in a function called "userval", and then modify those variables based on user input. Do I need to return these variables at the end of my function?
I am attempting to check my code by printing these global variables within the main function. However, I keep getting random characters.
Here is my code below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Global Constants
#define MAX_PSWD_LEN 80
char password = 0;
int len = 0;
int upper = 0;
int lower = 0;
int digit = 0;
int special = 0;
int main(int argc, char *argv[]) {
userval();
printf(&len);
printf(&upper);
printf(&lower);
printf(&digit);
printf(&special);
}
int userval() {
printf("Please enter the minimum length of your password: \n");
scanf("%d", &len);
printf("Please enter the minimum number of uppercase letters in your password: \n");
scanf("%d", &upper);
printf("Please enter the minimum number of lowercase letters in your password: \n");
scanf("%d", &lower);
printf("Please enter the minimum number of decimal digit characters in your password: \n");
scanf("%d", &digit);
printf("Please enter the minimum number of special characters in your password: \n");
scanf("%d", &special);
printf("Thank you. \n");
return len, upper, lower, digit, special;
}
That's not how the printf function works.
The first parameter is a format string. It contains any static text you want to print along with format specifiers for any values you want to print.
For example, if you want to print only a integer followed by a newline, the format string you would use is "%d\n", where %d is the format specifier for an integer and \n is a newline character.
Any subsequent parameters are used to fill in the format. In the case of the values you want to print, you would do the following:
printf("%d\n", len);
printf("%d\n", upper);
printf("%d\n", lower);
printf("%d\n", digit);
printf("%d\n", special);
The correct way to use it would be to
printf("%p\n",(void*)&len);
But this would print the address of the variable - most likely you want to print the value of the variable. (Holds for other int` variables also in your example).
printf("%d\n",len);
While using printf the first argument is the format string and the rest of the arguments are 0 or more variables (as dictated by format string).
From standard
int printf(const char * restrict format, ...);
This is the signature of the printf function. Also regarding the format specifier §7.21.6.1
The format shall be a multibyte character sequence, beginning and ending in its initial shift state. The format is composed of zero or more directives: ordinary multibyte characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments, converting them, if applicable, according to the corresponding conversion specifier, and then writing the result to the output stream.
Instead of any output stream it is stdout for printf.
Here Is code of Basic Structure , But the output is not as expected. There is three scanf function but only two is being executed. Middle one contains garbage value.
#include <stdio.h>
int main()
{
struct book
{
char name;
float price;
int pages;
};
struct book b1,b2,b3;
printf("Enter names , prices & no of pages of 3 books\n");
scanf("%c%f%d",&b1.name,&b1.price,&b1.pages);
scanf("%c%f%d",&b2.name,&b2.price,&b2.pages);
scanf("%c%f%d",&b3.name,&b3.price,&b3.pages);
printf("And this is what you entered\n");
printf("%c%f%d",b1.name,b1.price,b1.pages);
printf("%c%f%d",b2.name,b2.price,b2.pages);
printf("%c%f%d",b3.name,b3.price,b3.pages);
return 0;
}
Simply change
scanf("%c%f%d", &bx.name, &bx.price, &bx.pages);
To
scanf(" %c%f%d", &b1.name, &b1.price, &b1.pages);
After you press Enter, a '\n' is left in stdin, which will later be consumed by "%c". Having read a character('\n'), scanf() expects a floating-point number, as "%f" in the format string indicates. However, instead of getting that desired floating-point number, it meets a character, and it returns sadly. As a result, &bx.price and &bx.pages are not updated, so they remain uninitialised, giving you the garbage values.
With a leading space in scanf(), all whitespace characters(if any) are discarded before reading starts. Since \n is discarded, following reading process will(presumably) be successful.
Also, just a tip: Always check the return value of scanf(), because you'll never know that stuff users will input.
Example code:
#include <stdio.h>
struct book
{
char name;
float price;
int pages;
};
int main()
{
struct book b1, b2, ..., bx;
printf("Enter names, prices & no of pages of x books:\n");
while (scanf(" %c%f%d", &bx.name, &bx.price, &bx.pages) != 3)
{
fputs("Error reading bx. Please try again:\n", stderr);
scanf("%*[^\n] ");
}
......
printf("And this is what you have entered:\n");
printf("%c %f %d", bx.name, bx.price, bx.pages);
......
return 0;
}
Example input & output:
Enter names, prices & no of pages of x books:
asd wedewc efcew
Error reading bx. Please try again:
a 12.34 42
And this is what you have entered:
a 12.340000 42
scanf, usually, reads the characters from standard input stream, which includes your newlines as well as spaces. so try to flush all unwanted inputs left in the stdin stream before you use scanf("%c");
Also remember: do not let %c fall somewhere in the middle of the format string
Hope this could help. unfortunately you should use it before all scanf in "Your" program
printf("Enter names , prices & no of pages of 3 books\n");
fflush(stdin);
scanf("%c%f%d",&b1.name,&b1.price,&b1.pages);
You may also use a space before %c in scanf to read whitespaces.
scanf(" %c"....);
i am starting to learn C and I have ran into the problem of adding a string input to a 2D array, i am able to get the string input correctly but when i try and add the string element to the array it is not working as expected.When printing the array(which is how i test the program) it will assign each index in the array a single character instead of the entire string.
And here is my code for viewing, thank you very much in advance i appreciate any help that is posted.
#include <stdio.h>
main()
{
char c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
}
The output looks as follows with the sample input 'Penelope!'
c_array[0][0]=P
c_array[0][1]=e
c_array[0][2]=n
c_array[1][0]=e
c_array[1][1]=l
c_array[1][2]=o
c_array[2][0]=p
c_array[2][1]=e
c_array[2][2]=!
When you declare:
char c_array[3][3];
This means that each element of your 2D array is a "char" (a single character); not a "string of characters".
To have each element be a string of characters, you need to declare your array in the following way:
char string_array[3][3][256];
I am not sure this is what you want to do though. Mw feeling is that you want an array of 3 elements where each element is a string. In that case, [3] is hardly enough, your strings will have to be less than two characters (the third being reserved for the terminating zero).
Strings aren't a type. They're a value pattern, like if you say an int stores a multiple of ten, then it ends in 0... If you say an array of char stores a string, then it ends at the first '\0', see? We can store multiples of ten in different kinds of integer variables, and likewise for strings.
Strings are patterns of values, not types. When choosing which integer type we want to use, we consider the range for integers. We choose int for small integer values (less than 32768), long for larger values (less than 2147483648) or long long for values larger than that. As a result, we choose the correct type of integer depending on the multiple of ten we expect. Likewise for strings, we need to make sure we have enough memory for the characters in the string followed by the '\0' at the end.
The character &c_array[x][y] only has enough memory for 0 characters followed by a '\0' at the end; it's only useful for storing an empty string. Perhaps you meant to declare c_array like this:
char c_array[3][3][256];
In this case, scanf expects %s to correspond to an argument of the type char *... but as your compiler will probably warn you, &c_array[x][y] will have the type char (*)[256]. If you want to fix that warning, you'll need to remove the & from your scanf code:
if (scanf("%s", c_array[x][y]) != 1) {
/* XXX: Handle an error here, *
* e.g. by exiting or returning or something */
}
While we're on that topic, you'll notice that I removed the redundant space; %s already performs the functionality that the format directive would perform. I also wrote code to check the return value of scanf, as you should...
Remember how we spoke about choosing the types of integers that we use to store data? One other consideration is whether or not the data we intend to store can be negative. Consider this: In your code, should x and y be able to store negative values? What sense does a negative array index make? It is advisable that all array indexes be declared as size_t. When you use printf to print a size_t value, you'll want to use the %zu format specifier rather than %d.
char c_name[256];
/* ... */
printf("The string is %s\n",c_name);
Now, if the string is stored into c_array[x][y], then what is the point of c_name? That's an unnecessary variable. Use c_array[x][y], instead.
printf("\nPlease enter a name to the system:");
Common implementations will often refrain from printing characters until a '\n' is written; the line is printed all at once rather than character by character. As a result, you might see some strange behaviour such as this line not appearing at the right time. Fix this problem by putting the '\n' on the end of the line, rather than the beginning:
printf("Please enter a name to the system:\n");
... or use puts, which adds a '\n' for you automatically:
puts("Please enter a name to the system:");
... or use fflush, which will write all pending unwritten data even if there is no '\n':
fflush(stdout);
In your code
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
both the statements are wrong.
%s expects a pointer to an array, not a single char. To scan a single char, you need %c format specifier.
c_name, as used in the printf() is uninitialised. Using uninitialised value invokes undefined behaviour.
Solution: To take input element by element, you can do do something like
for(x=0; x<=2 ;x++)
{
printf("Start entering the name, one character at a time\n");
for(y=0; y< 2; y++) //note only '<' here
{
scanf(" %c", &c_array[x][y]); // note the leading space
}
c_array[x][y] = 0; //null termination of array to be used as string
}
If you want to assign a string to each index in the array, then create the array as follows :
#include<stdio.h>
int main(void)
{
char a[2][10];
int i=0;
char temp[20];
for(i=0;i<2;i++)
{
scanf("%s",temp);
strcpy(a[i],temp);
}
printf("%s",a[0]);
return 0;
}
Each string that you enter will be stored in each index of the array.
#include <stdio.h>
#include <string.h>
int main(void){
char c_array[3][3];
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
printf("\nPlease enter a name to the system:");
scanf("%255s",c_name);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
if(i_user_input==1)
;
else if(i_user_input==2){
memcpy(c_array, c_name, sizeof(c_array));
for(x=0;x<3;x++){
for(y=0;y<3;y++){
printf("c_array[%d][%d]=%c\n", x, y, c_array[x][y]);
}
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3
int main(void){
char *c_array[SIZE][SIZE] = { NULL };
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
printf("\nPlease enter a name to the system:");
scanf("%255s", c_name);
printf("The string is %s\n", c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
c_array[x][y] = strdup(c_name);
if(i_user_input==1){
continue;
}
if(i_user_input==2){
int x, y;//local variable
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
if(c_array[x][y] != NULL)
printf("c_array[%d][%d]=%s\n", x, y, c_array[x][y]);
}
}
}
}
}
for(x=0;x<SIZE;x++)
for(y=0;y<SIZE;y++)
free(c_array[x][y]);
}
Why not use pointers in you array/matrix?
#include <stdio.h>
#include <string.h>
main()
{
char *c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",c_name);
new_string = malloc(strlen(c_name)+1)
if (new_string == NULL) {
print("error allocating string\n")
exit(-1);
}
strcpy(new_string, c_name);
c_array[x][y] = new_string
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
for(x=0;x<=2;x++) {
for(y=0;y<=2;y++) {
free(c_array[x][y])
}
}
}
The code above stores the input string in each cell of the array, if that is your goal.
Note: I have no tried it, so there may be subtle errors. My point is to show you how to use pointers and their equivalence to arrays. Using C without pointers is pointless. :)
I'm a student studying C, and seem to be stuck when using Structures and Arrays to read in characters as part of the array.
When I run the code, it skips over the char scanf and will not read in any characters. There is no problem reading in integers etc.
For example (This is an example, my code is much longer but I know there's a problem here). Is the scanf part that reads in the name correct?
struct stud s[5];
int i = 0;
for (int i = 0; i < 5; i++)
{
fflush(stdout);
s[i].no = i + 1;
printf("\nStud number %d\n", s[i].no);
printf("Enter name:");
scanf_s("%c", &s[i].name);
printf("Enter grade: ");
scanf_s("%d", &s[i].grade);
printf("Successfully added to grade book\n");
}
I declared them below:
struct stud {
int no;
char name;
int grade;
};
It would be great if someone could point me in the correct direction?
You have to declare name as a char array
struct room {
int no;
char name[32]; /* pick a reasonable size */
int grade;
};
And then this
scanf_s("%c",&s[i].name);
would change to
scanf_s("%s",s[i].name, _countof(s[i].name));
and since there is no guarantee that the name would be 31 characters length, you have to specify a field length like this
scanf_s("%31s",s[i].name, _countof(s[i].name));
the length should be the sizeOfArray - 1 since c strings need to mark the end of the string with a null byte '\0', and scanf_s will append that byte to the read string.
If you don't specify the field length and it turns out that there are more than characters than requested by _countof(s[i].name) then nothing is read, for more information read here.
Note that you should create a char array of a reasonable size and use %s as mentioned by #iharob in his answer if you want to enter more than 1 character for a student. If you want name to be a char,then change
scanf_s("%c", &s[i].name);
To
scanf_s(" %c", &s[i].name, 1);
The space before %c skips all kinds of blanks(like newlines and spaces) present in the stdin and %c will then scan a non-whitespace character.
The %c will not the characters because the characters will be present in stdin, and you have to skip the characters.
scanf_s("%c", &s[i].name);
if the last character in the previous is \n the %c will take the \n as input.
You have to change the code, just give a space before the %c.
scanf_s(" %c", &s[i].name);
This will flush the white space characters in the stdin and it will get the input.
Take for example
int i=10,j;
float b=3.14,c;
char str[30];
sprintf(str,"%d%f",i,b);
sscanf(str,"%d%f",&j,&c);
printf("%d ----- %f\n",j,c);
OUTPUT :- 103 ----- 0.1400000
As you can see, initially i=10 and b=3.14.
I want that j=10 and c=3.14 by using sprint() and sscanf().
The problem I am facing is that the compiler assigns j=103 and c=0.140000.
Is there any way to get rid of this problem in sscanf()?
Add one space to sprintf. Change:
sprintf(str,"%d%f",i,b)
to
sprintf(str,"%d %f",i,b)
Aside: It would be also safer to use snprintf here:
snprintf(str, sizeof str, "%d %f", i, b)
The best way will be to separate the numbers, using a different sign, but if you know that the first int is 2 chars long you can specify it:
sscanf(str,"%2d%f",&j,&c);
// ^^
You are missing a space
Change
sprintf(str,"%d%f",i,b);
to
sprintf(str,"%d %f",i,b);
#include <stdio.h>
int main()
{
int i=10,j;
float b=3.14,c;
char str[30];
sprintf(str,"%d %f",i,b);
sscanf(str,"%d%f",&j,&c);
printf("%d ----- %f\n",j,c);
return 0;
}
output
~ > ./a.out
10 ----- 3.140000
The %d conversion specifier in sscanf will match any number of contiguous numeric characters in the buffer pointed to by str till it encounters a non-numeric character which it can't match. This will cause the integral part of the float to be read as part of the int value. Therefore you must have a way to separate where you integer ends and float starts in the string str. You can put any non-numeric character as a sentinel to separate int value from the float value.
int i = 10, j;
float b = 3.14, c;
char str[30];
// a # to separate the two values, can be any non-numeric char so that it
// is not mistaken for a digit in the int or float value
sprintf(str,"%d#%f", i, b);
// match the separator character to read int and then float
sscanf(str, "%d#%f", &j, &c);