Using struct and point to input and output info - c++

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().

Related

error: variable or field 'Palindrome' declared void in c++

I'm getting this error hence I am new to c++ I could not understand
please help me!!!
I am writing a palindrome code
This is the code given below:.............
I am basically here using some extra concepts not doing in-direct fashion.
if anyone can post the correct code he/she is most welcome...
//palindrome
#include <cstring> //or use #include <string.h>
#include <iostream>
using namespace std;
void Palindrom(string& );
void Palindrome(string& word)// same as (const string& word)
{
int n = word.length();
string word2;
char reverse[n];
for(int i = 0; i <=n; i++){
word[i]=tolower(word[i]);
}
word2=word; //now both are small
for(int i = n-1; i >=0; i--){
reverse[n-1-i]=word2[i];
cout<<reverse[n-1-i];
}
for(int i =0; i >n; i++){ //printing reversed
cout<< " Reverse: "<<reverse[i]<<endl;
}
// word is ok and word2 gets reversed
for (int i = 0; i <= n; i++){
if(word[i]==reverse[i])
{
cout<<"\nit is palandrome ";
}
cout<<"\nit is not a palindrome ";
}
}
int main()
{ string k="YuUuy";
void Palindrome(k);
return 0;
}
Correct syntax for calling a function is Palindrome(k); without the void.
Few remarks:
Get a good c++
book.
// same as (const string& word) is not true.
You did not include <string> header.
It's good practice to use std::size_t for indices, but beware of unsigned>=0 condition being always true.
char reverse[n]; is wrong, n must be a compile-time constant, VLA are not part of the C++ standard.
Function calls should not have return type. Change void Palindrome(k); in main() function to Palindrome(k);
While declaring array, the expression should have constant value. So you can't use char reverse[n];. Change it to char *reverse = new char[n]; and deallocate it using delete[] reverse; after you are done using it.
I would recommend you to use smart pointer. You should also take a look at std::string instead of using stream of char.

Garbage values are printing even after null character

This code is for printing left recursion alternatives in a production.But when printing alternatives at last garbage values are being added.Why am i getting such error?
how to resolve such problem?in the image the output is displayed.but that is the wrong output
#include<iostream>
#include<cstring>
using namespace std;
class production
{
private:
char lhs;
char rhs[10][10],lr[10][10];
int noa;
public:
production()
{
noa=0;
}
void makeprod(char *str)
{
lhs=str[0];
char r[20];
strcpy(r,str+3);
int j=0;
for(int i=0;r[i]!='\0';i++)
{
if(r[i]!='/')
rhs[noa][j++]=r[i];
else
{
rhs[noa++][j]='\0';
j=0;
}
}
noa++;
}
void checkLR()
{
int ct=0,m=0;
for(int i=0;i<noa;i++)
if(lhs==rhs[i][0])
{
strcpy(lr[m],rhs[i]);
m++;
ct++;
}
if(ct>0)
{
for(int k=0;k<ct;k++)
cout<<"Left recursion at "<<lr[k]<<"\n";
}
else
cout<<"no\n";
}
void printprod()
{
cout<<"LHS = "<<lhs<<"\n";
cout<<"RHS = ";
for(int i=0;i<noa;i++)
cout<<rhs[i]<<" ";
}
};
int main()
{
production p;
char str[20];
cout<<"enter a production\n";
cin>>str;
p.makeprod(str);
p.printprod();
p.checkLR();
return 0;
}
In makeprod you're checking your input string for / to add the termination character to your rhs-array, and thus your input string has to end with the / sign. You have several choices :
either initialize your arrays with 0, so the rhs-array is always null-terminated (independently from your question : It's always good practice to initialize your variables)
add a null-termination sign (0) to rhs when the end of your input string is reached
edit: Just place a memset(rhs, 0, sizeof(rhs)*sizeof(char)); (the same for lr) in your constructor and the output should be fine. This will initialize your arrays with zeroes and thus the string is null-terminated.
But you really should add some overflow checking.
You are propably incrementing noa one time too much in makeprod().
That makes the for loop in printprod() access rhs 1 element after its end.

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;

Bubble sort names in ascending order in a structure containing name and marks

When I call the function and then display it, the output is same as the input. There is no other error in the program, which should mean taht there is some problem in the function. I'm just a beginner so any help is appreciated.
#include <iostream>
using namespace std;
struct student
{
char name[30];
int marks;
void getinfo()
{
cout<< "Enter your name:\n"; cin>>name;
cout<<"Enter marks:\n"; cin>>marks;
}
void showinfo()
{
cout<<"\nName: "<<name<<endl;
cout<<"Marks: "<<marks<<endl<<endl;
}
};
void bubsort( student S[] , int N)
{
student Temp;
for(int i=0;i<N-1;i++)
for(int j=0;j<N-1-i;j++)
{
if(S[j].name>S[j+1].name)
{
Temp=S[j];
S[j]=S[j+1];
S[j+1]=Temp;
}
}
}
int main()
{
student A[5];
cout<<" Enter details for 5 students:\n";
for( int i=0;i<5;i++)
A[i].getinfo();
bubsort(A,5); //I used the function
cout<<" Sorted information:\n";
for( int j=0;j<5;j++)
A[j].showinfo(); //result is in the same order as input
}
Arrays decays to pointers, so your comparison S[j].name>S[j+1].name is comparing pointers and not the strings.
If you want to compare string you need to use either std::string instead of character arrays, or use strcmp.

Reverse String C++ using char array

I wrote a simple C++ program to reverse a string. I store a string in character array. To reverse a string I am using same character array and temp variable to swap the characters of an array.
#include<iostream>
#include<string>
using namespace std;
void reverseChar(char* str);
char str[50],rstr[50];
int i,n;
int main()
{
cout<<"Please Enter the String: ";
cin.getline(str,50);
reverseChar(str);
cout<<str;
return 0;
}
void reverseChar(char* str)
{
for(i=0;i<sizeof(str)/2;i++)
{
char temp=str[i];
str[i]=str[sizeof(str)-i-1];
str[sizeof(str)-i-1]=temp;
}
}
Now this method is not working and, I am getting the NULL String as result after the program execution.
So I want to know why I can't equate character array, why wouldn't this program work. And what is the solution or trick that I can use to make the same program work?
sizeof(str) does not do what you expect.
Given a char *str, sizeof(str) will not give you the length of that string. Instead, it will give you the number of bytes that a pointer occupies. You are probably looking for strlen() instead.
If we fixed that, we would have:
for(i=0;i<strlen(str)/2;i++)
{
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
}
This is C++, use std::swap()
In C++, if you want to swap the contents of two variables, use std::swap instead of the temporary variable.
So instead of:
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
You would just write:
swap(str[i], str[sizeof(str) - i - 1]);
Note how much clearer that is.
You're using C++, just use std::reverse()
std::reverse(str, str + strlen(str));
Global variables
It's extremely poor practice to make variables global if they don't need to be. In particular, I'm referring to i about this.
Executive Summary
If I was to write this function, it would look like one of the two following implementations:
void reverseChar(char* str) {
const size_t len = strlen(str);
for(size_t i=0; i<len/2; i++)
swap(str[i], str[len-i-1]);
}
void reverseChar(char* str) {
std::reverse(str, str + strlen(str));
}
When tested, both of these produce dlrow olleh on an input of hello world.
The problem is that within your function, str is not an array but a pointer. So sizeof will get you the size of the pointer, not the length of the array it points to. Also, even if it gave you the size of the array, that is not the length of the string. For this, better use strlen.
To avoid multiple calls to strlen, give the function another parameter, which tells the length:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
and call it with
reverseChar(str, strlen(str))
Another improvement, as mentioned in the comments, is to use std::swap in the loop body:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
std::swap(str[i], str[len-i-1]);
}
}
Also, there is std::reverse which does almost exactly that.
//reverse a string
#include<iostream>
using namespace std;
int strlen(char * str) {
int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
void reverse(char* str, int len) {
for(int i=0; i<len/2; i++) {
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
int main() {
char str[100];
cin.getline(str,100);
reverse(str, strlen(str));
cout<<str<<endl;
getchar();
return 0;
}
If I were you, I would just write it like so:
int main()
{
string str;
cout << "Enter a string: " << endl;
getline(cin, str);
for (int x = str.length() - 1; x > -1; x--)
{
cout << str[x];
}
return 0;
}
This is a very simple way to do it and works great.
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char str[80];
cout << "Enter a string bro: \n";
gets_s(str);
for (int i = strlen(str) - 1; i > -1; i--)
{
cout << str[i];
}
}