compare fgets to the user input - strcmp

can you help me with my code? I want to do a program that will determine if the student id was already used, i can compare them once... but what i want to do is to have a comparison every time the user inputs another student id so... the program will know if the user inputs another used id, i know i need to have a loop before the "Enter student id:".. but still having a hard time to think for the conditions, or if you have a better solutions... i would be happy using it..
guys this is my code:
#include<stdio.h>
#include<stdlib.h>
struct studentinfo{
char id[8];
char name[30];
char course[5];
}s1;
main(){
int i=0;
int count=0;
char arr[50];
FILE *stream = NULL;
stream = fopen("studentinfo.txt", "a+");
struct studentinfo *array[50];
array[i] = (struct studentinfo*) malloc(sizeof(struct studentinfo));
printf("Enter Student ID: ");
scanf("%s", array[i]->id);
fflush(stdin);
while(!feof(stream)){
fgets(arr, 6, stream);
if(strcmp(arr, array[i]->id)==0){
printf("Student ID is used!\n");
free(array[i]);
}
}
printf("Enter Student Name: ");
gets(array[i]->name);
fflush(stdin);
printf("Enter Student Course: ");
scanf("%s", array[i]->course);
fprintf(stream, "\n%s,\t%s,\t%s", array[i]->id, array[i]->name, array[i]->course);
i++;
fclose(stream);
i=0;//for freeing the space
if(array[i] != NULL){
free(array[i]);
}
getch();
}

i was advice to use goto function... and it solve the problem but i was kinda worried because there might have a bug i haven't encountered yet, this is my new code:
#include<stdio.h>
#include<stdlib.h>
struct studentinfo{
char id[8];
char name[30];
char course[5];
}s1;
main(){
int i=0;
int count=0;
char arr[50];
FILE *stream = NULL;
stream = fopen("studentinfo.txt", "a+");
struct studentinfo *array[50];
array[i] = (struct studentinfo*) malloc(sizeof(struct studentinfo));
studid:
printf("Enter Student ID: ");
scanf("%s", array[i]->id);
fflush(stdin);
while(!feof(stream)){
fgets(arr, 6, stream);
if(strcmp(arr, array[i]->id)==0){
printf("Student ID is used!\n");
goto studid;
}
}
printf("Enter Student Name: ");
gets(array[i]->name);
fflush(stdin);
printf("Enter Student Course: ");
scanf("%s", array[i]->course);
fprintf(stream, "\n%s,\t%s,\t%s", array[i]->id, array[i]->name, array[i]->course);
i++;
fclose(stream);
if(array[i] != NULL){
free(array[i]);
}
getch();
}
any other better solutions thnx ^_^

Related

Mapping string to int CPP - Output hangs during execution

I am currently doing a practice problem in hacker rank. The link is : https://www.hackerrank.com/challenges/linkedin-practice-dictionaries-and-maps
#include<cstdio>
#include<map>
#include<vector>
#include<conio.h>
#include<iostream>
#include<string>
using namespace std;
map<std::string, int> dict;
map<std::string, int>::iterator k;
int i, j, temp, n;
long long num;
//char check[100][100];
std::string str, sea;
int main()
{
scanf("%d", &n);
j = n;
while(j--)
{
scanf("%s %d", &str, &num);
dict.insert(make_pair(str, num));
}
printf("finished\n");
printf("%s %d\n", "sam", dict["sam"]);
while(scanf("%s", str))
{
if(str.empty())
break;
//printf("k is %s\n",str);
k = dict.find(str);
if(k != dict.end())
{
printf("%s %d\n", str, dict[str]);
}
else
{
printf("Not found\n");
}
}
getch();
}
The program runs fine until the printf statement "finished". Then in the next output for the dict statement occurs as
finished
sam 0
And in while statement, when it searches for string in map, the application hangs, and closes automatically. While inserting values I tried to use:
dict[str] = num;
dict.insert(pair(str, num));
dict.insert(make_pair(str, num));
Please mention if there is any corrections I need to do in the program. Any help is appreciated. Thanks!
This statement,
scanf("%s %d", &str, &num);
… is not a valid way to input a std::string. It has Undefined Behavior. All bets are off.
You can input to a char buffer, and conveniently std::string provides such a buffer. E.g.
str.resize( max_item_length );
scanf("%s %d", &str[0], &num);
str.resize( strlen( &str[0] ) );
Of course you can just use C++ iostreams instead, throughout the code, e.g.
cin >> str >> num;

How do I scan in an N number of strings (using structs) and then output that list of strings in reverse?

Using the specific struct below,
struct Student
{
char first[50];
char last[50];
char id[20];
};
How do I scan in an N number of strings consisting of first name, last name and ID number and then output that entire list backwards?
For example:
Input:
3
Dent Arthur 12345ABC
Prefect Ford 54321CBA
McMillan Tricia AB9876
Output:
McMillan Tricia AB9876
Prefect Ford 54321CBA
Dent Arthur 12345ABC
Here's what I have so far
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student NAME;
for(i=0; i<N; i++){
scanf("%s %s %s", NAME.first[i], NAME.last[i], NAME.id[i]);
}
/*struct Student prefect;
scanf("%s %s %s", &prefect.first, &prefect.last, &prefect.id);
struct Student mcmillan;
scanf("%s %s %s", &mcmillan.first, &mcmillan.last, &mcmillan.id);*/
printf("\n");
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
return 0;
}
If you want to print the list (array) in a reverse manner,
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", NAME.first[i], NAME.last[i], NAME.id[i]);
}
This fixes the reversing problem, although there is one more problem in the code. You have declared the members of struct to be of type string, and in the main function, you treat them as an array of strings. This won't work. You probably wanted to have an array of struct objects. This is how to go about it:
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student NAME[10];
for(i=0; i<N; i++){
scanf("%s %s %s", NAME[i].first, NAME[i].last, NAME[i].id);
}
/*struct Student prefect;
scanf("%s %s %s", &prefect.first, &prefect.last, &prefect.id);
struct Student mcmillan;
scanf("%s %s %s", &mcmillan.first, &mcmillan.last, &mcmillan.id);*/
printf("\n");
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", NAME[i].first, NAME[i].last, NAME[i].id);
}
return 0;
}
Link to ideone: http://ideone.com/hgPjjn
suggest modifying the struct to include a 'previous' and 'next' pointers
and putting the structs into a linked list.
perhaps by malloc'ing the struct instances, as each data becomes available.
linking the malloc'd struct onto the end of the linked list.
then to output,
walk down to the end of the list
then
printing current value,
step to previous list entry,
print value, etc
until back at the head pointer for the list.
could also insert each struct entry at the beginning of
the linked list,
that would avoid having to walk down the list
to find the last struct, before being able to print
You have made a bit error while tacking the students from console. First of all for taking the all student you have to create a array of struct Student-
struct Student students[100];
Then you may take the input from the user like this -
for(i=0; i<N; i++){
scanf("%s %s %s", students[i].first, students[i].last, students[i].id);
}
And after that all things remain same.When we write the complete code it would be -
#include <stdio.h>
#include <string.h>
struct Student
{
char first[50];
char last[50];
char id[20];
};
int main( )
{
int N, i;
scanf("%d", &N);
struct Student students[100];
for(i=0; i<N; i++){
scanf("%s %s %s", students[i].first, students[i].last, students[i].id);
}
printf("\n");
for(i=N-1; i>=0; i--){
printf("%s %s %s\n", students[i].first, students[i].last, students[i].id);
}
return 0;
}
This will work
#include <stdio.h>
#include <string.h>
struct Student {
char first[50];
char last[50];
char id[20];
};
int main() {
int N, i;
scanf("%d", &N);
struct Student NAME[N];
for (i = 0; i < N; ++i)
scanf("%s %s %s", NAME[i].first, NAME[i].last, NAME[i].id);
printf("\n");
for (i = N - 1; i >= 0; --i)
printf("%s %s %s\n", NAME[i].first, NAME[i].last, NAME[i].id);
return 0;
}

Read two words into one char array element

I am trying to read in two words from text file into one char array element. I CANNOT USE std::string. I get a seg fault because my loop is looping in a way that goes out of bounds. I cannot copy in the two words. please help me do this!! My loop for card struct works perfectly. I cannot get the "first last" into the people[].name
// deck of cards
// below are initializations
#include
#include
#include
#include
#include
using namespace std;
//globals
const int maxCards = 52;
//Structs
struct card {
char suit[8];
char rank[6];
int cvalue;
char location;
};
struct player {
char name[100];
int total;
card hand[4];
};
//program
int main()
{
//constants
char tempfName[100];
char templName[100];
//create struct array(s)
card deck[52];
card shuffledDeck[52];
player people[4];
//create pointers
card * deckPointer =NULL;
deckPointer = deck;
card * shuffledDeckPointer=NULL;
shuffledDeckPointer = shuffledDeck;
for(int i=0;i<4;i++)
{
strcopy(people[i].name,"first last");
}
//open player names file
ifstream fin2;
string fin2Name;
//get file name from user
cout << "Enter player file name...(Players.txt)" << endl;
getline(cin, fin2Name);
//open file
fin2.open(fin2Name.c_str());
//check if Players.txt opens correctly
if(!fin2.good())
{
cout << "Error with player file!" << endl;
return 0;
}
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
//now add space after first name
tempfName[length] = ' ';
length++;
while(templName[index] != '\0')
{
tempfName[length] = templName[index];
length++;
index++;
}
tempfName[length]='\0';
int counter =0;
while(templName[counter] != '\0')
{
people[0].name[counter] = templName[counter];
counter++;
}
}
}
it seems your tempfName is not pointing to a correct object in your while loop in else statement
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
You could do some cheating:
char full_name[256]; // Binary quantities are better.
snprintf(full_name, sizeof(full_name),
"%s %s",
first_name, last_name);
You should do more research regarding C-style string functions, like check a good reference book. It should have a chapter about the C-style string functions.
Here are some helpful ones:
strcpy, strcat, strchr, sprintf, strlen

Call function passing array's

I want to enter the text and specific character.
After that i want to count how many those characters contain in the text.
My code
#include <stdio.h>
#include <stdlib.h>
int counting(char text[], char character);
int main()
{
char text[20];
char character;
int a;
printf("Enter text!\n");
scanf("%s", text);
printf("Enter character!\n");
scanf("%s", character);
a= counting(text, character);
printf("Text contain %d character!\n", a);
}
And the counting function
int counting(char text[], char character)
{
int i=0;
int counter=0;
while(text[i] != '\0')
{
if (text[i]==character)
{
counter++;
}
}
i++;
return counter;
}
Error:
The line for reading the character needs to be:
scanf(" %c", &character);
Also,
scanf("%s", text);
is not safe. If the user enter a string that is longer than 19 characters, you will be writing over unauthorized memory, which will lead to undefined behavior.
Use
scanf("%19s", text);
In function int counting(...)
while(text[i] != '\0')
{
if (text[i]==character)
{
counter++;
}
}
i++;
Need i++ inside your while..loop.
You have two problems.
1)You are reading the specific character as a string so you have to change scanf("%s", character); to scanf(" %c", character);
2)In function counting() i++ needs to be in while loop so you don't enter an infinite loop.

Using struct and point to input and output info

I have a problem with inputting a string pointer in struct. This is my code:
typedef struct{
char *name;
int age;
}stu;
void allocate(stu* &s, int n){
s = (stu*) malloc(n * sizeof(stu));
if(s == NULL){
printf("\nNot enought memory!");
exit(1);
}
}
// Input info
void input_info(stu* &s, int n){
void input(stu &s); //prototype
for(int i = 0; i < n; i++){
printf("\n-- Student #%d:", i+1);
input(*(s+i));
}
}
void input(stu &s){
fflush(stdin);
printf("\nEnter student's name: ");
gets(s.name);
printf("\nEnter student's age: ");
scanf("%d", &s.age);
}
// End input
//Output info
void output_info(stu* s, int n){
void output(stu s); //prototype
for(int i = 0; i < n; i++){
printf("\n-- Student #%d:", i+1);
output(*(s+i));
}
}
void output(stu s){
printf("\nName: %s", s.name);
printf("\nAge: %d", s.age);
}
//End output
int main(){
stu* s;
int n;
printf("How many students you want to input?: ");
scanf("%d", &n);
allocate(s, n);
input_info(s, n);
output_info(s, n);
getch();
}
When I input second student's name, it's breaked? I allocated memory. And I want to ask how to deallocate memory for stu pointer? Thanks for reading
There are many things that can and should be improved in your program. Some suggestions:
Remove the char * member replace it with std::string. You don't want to do manual memory management for anything unless you really want to.
Drop the silly scanf and printf, they are not type safe. Since you are using C++ use std::cin and std::cout and you are much safer than usage with later.
Drop the fflush(stdin), Calling fflush on anything other than stdout gives you undefined behavior.
In C++, You would usually want to use new and not malloc. Avoid using dynamic memory allocation at all, if you can. Prefer to use a std::vector instead.
Online Sample:
Following the above suggestions your example can be written as:
#include<string>
#include<vector>
#include<iostream>
typedef struct
{
std::string name;
int age;
}student;
// Input info
void input_info(std::vector<student> &s)
{
student obj;
std::cout<<"\nEnter Students name";
std::cin>>obj.name;
std::cout<<"\nEnter Students age";
std::cin>>obj.age;
s.push_back(obj);
}
// Output info
void output_info(const std::vector<student> &s)
{
for (auto itr = s.cbegin(); itr != s.cend(); ++itr)
{
std::cout<<"\nName:"<< itr->name;
std::cout<<"\nAge:"<< itr->age;
}
}
int main()
{
int n;
std::cout<<"How many students you want to input?\n";
std::cin>>n;
std::vector<student>s;
for(int i = 0; i<n; i++)
{
input_info(s);
}
output_info(s);
return 0;
}
As some of the previous poster have mentioned, the code is not "pure" c++, as it mixes a lot of C and C++ features. Personally I think it is a less problematic when dealing with POD structs, like yours.
The crash is likely caused by gets(). It assumes that the char pointer is already allocated with a suitable capacity. It has undefined behavior when the inputs strings is longer than the capacity. Your capacity is 0, hence the crash.
If you insist on using C functions, see: Safe Alternative to gets.
Otherwise lookup getline().