Read line by line from text file c++ - visual-c++

I have a file with random data for accounts.
The data in the file:
5
2871 2.19 8
1234 95.04 23
3341 0.00 10
3221 -1.08 21
7462 404.14 4
3425 4784.00 200
3701 99.50
JUNK SHOULD NEVER GET HERE
3333
The first number 5 will always be the number of accounts that need to be processed.
I want to be able to read that number and set it as the number of accounts.
So my question is how can I read the file and read line by line and set the first number to the number of accounts that need to be processed.
Code so far:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
double NumberOfAccounts;
ifstream File("test.dat");
string line;
if(File)
{
while(getline(File,line))
{
NumberOfAccounts=line[0];
}
File.close();
}
cout<<NumberOfAccounts;
system("pause");
return 0;
}
Right now it just prints out 51.
Any tips/help would be appreciated.

Two things. One, you're getting stuck in a while loop (while there's a line left, read it in and re-assign the number of accounts) until the end of the file. Secondly, ASCII numbers do not correspond to actual numbers, so the character "0" is actually the number 48. You're getting 51 as the program reads the last line, finds the "3" character, assigns that to an integer (which is now 51), then outputs it.

NumberOfAccpounts is double, you are assigning the first character of line...
I assume you menat the first line in the file.
My C++ is crap so
pseudocode
if(File)
{
if getLine(File, line)
{
NumberOfAccounts =atof(line);
}
File.close();
}
cout<<NumberOfAccounts;
system("pause");
return 0;
atof is one way to convert a string to a double. You don't need to read the entire file to get the first line.

Related

C Function to return a String resulting in corrupted top size

I am trying to write a program that calls upon an [external library (?)] (I'm not sure that I'm using the right terminology here) that I am also writing to clean up a provided string. For example, if my main.c program were to be provided with a string such as:
asdfFAweWFwseFL Wefawf JAWEFfja FAWSEF
it would call upon a function in externalLibrary.c (lets call it externalLibrary_Clean for now) that would take in the string, and return all characters in upper case without spaces:
ASDFFAWEWFWSEFLWEFAWFJAWEFFJAFAWSEF
The crazy part is that I have this working... so long as my string doesn't exceed 26 characters in length. As soon as I add a 27th character, I end up with an error that says
malloc(): corrupted top size.
Here is externalLibrary.c:
#include "externalLibrary.h"
#include <ctype.h>
#include <malloc.h>
#include <assert.h>
#include <string.h>
char * restrict externalLibrary_Clean(const char* restrict input) {
// first we define the return value as a pointer and initialize
// an integer to count the length of the string
char * returnVal = malloc(sizeof(input));
char * initialReturnVal = returnVal; //point to the start location
// until we hit the end of the string, we use this while loop to
// iterate through it
while (*input != '\0') {
if (isalpha(*input)) { // if we encounter an alphabet character (a-z/A-Z)
// then we convert it to an uppercase value and point our return value at it
*returnVal = toupper(*input);
returnVal++; //we use this to move our return value to the next location in memory
}
input++; // we move to the next memory location on the provided character pointer
}
*returnVal = '\0'; //once we have exhausted the input character pointer, we terminate our return value
return initialReturnVal;
}
int * restrict externalLibrary_getFrequencies(char * ar, int length){
static int freq[26];
for (int i = 0; i < length; i++){
freq[(ar[i]-65)]++;
}
return freq;
}
the header file for it (externalLibrary.h):
#ifndef LEARNINGC_EXTERNALLIBRARY_H
#define LEARNINGC_EXTERNALLIBRARY_H
#ifdef __cplusplus
extern "C" {
#endif
char * restrict externalLibrary_Clean(const char* restrict input);
int * restrict externalLibrary_getFrequencies(char * ar, int length);
#ifdef __cplusplus
}
#endif
#endif //LEARNINGC_EXTERNALLIBRARY_H
my main.c file from where all the action is happening:
#include <stdio.h>
#include "externalLibrary.h"
int main() {
char * unfilteredString = "ASDFOIWEGOASDGLKASJGISUAAAA";//if this exceeds 26 characters, the program breaks
char * cleanString = externalLibrary_Clean(unfilteredString);
//int * charDist = externalLibrary_getFrequencies(cleanString, 25); //this works just fine... for now
printf("\nOutput: %s\n", unfilteredString);
printf("\nCleaned Output: %s\n", cleanString);
/*for(int i = 0; i < 26; i++){
if(charDist[i] == 0){
}
else {
printf("%c: %d \n", (i + 65), charDist[i]);
}
}*/
return 0;
}
I'm extremely well versed in Java programming and I'm trying to translate my knowledge over to C as I wish to learn how my computer works in more detail (and have finer control over things such as memory).
If I were solving this problem in Java, it would be as simple as creating two class files: one called main.java and one called externalLibrary.java, where I would have static String Clean(string input) and then call upon it in main.java with String cleanString = externalLibrary.Clean(unfilteredString).
Clearly this isn't how C works, but I want to learn how (and why my code is crashing with corrupted top size)
The bug is this line:
char * returnVal = malloc(sizeof(input));
The reason it is a bug is that it requests an allocation large enough space to store a pointer, meaning 8 bytes in a 64-bit program. What you want to do is to allocate enough space to store the modified string, which you can do with the following line:
char *returnVal = malloc(strlen(input) + 1);
So the other part of your question is why the program doesn't crash when your string is less than 26 characters. The reason is that malloc is allowed to give the caller slightly more than the caller requested.
In your case, the message "malloc(): corrupted top size" suggests that you are using libc malloc, which is the default on Linux. That variant of malloc, in a 64-bit process, would always give you at least 0x18 (24) bytes (minimum chunk size 0x20 - 8 bytes for the size/status). In the specific case that the allocation immediately precedes the "top" allocation, writing past the end of the allocation will clobber the "top" size.
If your string is larger than 23 (0x17) you will start to clobber the size/status of the subsequent allocation because you also need 1 byte to store the trailing NULL. However, any string 23 characters or shorter will not cause a problem.
As to why you didn't get an error with a string with 26 characters, to answer that one would have to see that exact program with the string of 26 characters that does not crash to give a more precise answer. For example, if the program provided a 26-character input that contained 3 blanks, this would would require only 26 + 1 - 3 = 24 bytes in the allocation, which would fit.
If you are not interested in that level of detail, fixing the malloc call to request the proper amount will fix your crash.

I'm need to count every word, line , and character of a given string

as you can see i'm trying to get the word count, character count and line count but the below code is not working.
#include<iostream>
using namespace std;
int main()
{
char ch;
int wc=1, lc=1, cc=0;
while((ch=cin.get())!='*')
{
cc++;
if(ch==' ')
{
wc++;
}
else if(ch=='\n')
{
wc++;
lc++;
}
}
cout<<"\n the number of character=="<<cc;
cout<<"\n the number of words=="<<wc;
cout<<"\n the number of lines=="<<lc;
return 0;
}
I entered your code and compiled it with g++. It is working without any problems. Can you post the error you get or did it compile ?
Maybe your visual c++ compiler is not working right. The code itself should work.
Edit: Below a different version of the above code, where no text input is threaded as zero words and EOF is also a break condition of the loop.
EOF depends on your system, on Windows it is Control + z, on Linux it might be Control + d.
The input text might have multiple spaces between words. Punctuation characters and digits (0-9) are threaded as word delimiters as good as possible. Underscore, backticks, tildes and apostrophe like in "don't" are handled as part of a word.
Curly brackets are handled as part of a word to keep the code simple but normal brackets are delimiters.
#include <iostream>
using namespace std;
int main()
{
int ch, wc=0, lc=1, cc=0, old=0;
cout<<"Enter your text, exit with '*':\n";
while ((ch=cin.get())!='*' && ch!=EOF)
{
cc++;
if (old<='?' && old!='\'')
wc += !(ch<='?' && ch!='\'');
lc += ((old=ch)=='\n');
}
cout<<"\nthe number of character=="<<cc
<<"\nthe number of words=="<<wc
<<"\nthe number of lines=="<<lc<<"\n";
return 0;
}

If statements in my C code are doing the exact opposite of the conditions?

So i'm comparing two strings and my code is doing the exact opposite of what it should be doing. I can't switch up my printf statements because then that would also be wrong. If i input the first string that has length 5 and a second string with length 6, it will say that string 1 is GREATER than string 2 when it's the exact opposite.
Here is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char str1[100], str2[100];
printf("enter the first string :");
scanf("%s", &str1);
printf("enter the second string :");
scanf("%s", &str2);
if(strcmp(str1,str2)==0){
printf("the strings are equal\n");
}
else if(strcmp(str1,str2)<0){
printf("string 1 is less than string 2\n");
}
else{
printf("string 1 is greater than string 2\n");
}
return 0;
}
strcmp doesn't compare the lengths of strings. It compares characters until it founds two that are not the same, then returns a negative or positive number depending on which string had the character earlier in the alphabet. If one string runs out ("Hello" vs. "Hell") then the shorter one comes first. And if they are identical then the result is 0.
For example, "xyz" > "abcde" because x comes after a.
Strcmp compares the strings according to the alphabetical order.
To compare the length of the strings, just replace strcmp() with strlen().

picking up random numbers from a text file in c++

If a text file contains numbers in 100 rows * 100 columns (for example). Now i want my program to pick up ,for example , one number from 60th row and 97th column and then assign this value to a variable and perform some calculation with this variable. So i want to pick up some random numbers from a text file which contains a lot of numbers. how can i do that??
I made a code for practice but its giving some error.
the text file contains 6 different digits in 2 rows and 3 columns
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
int data[6],i=0;
ifstream myfile;
myfile.open ("a.txt");
while (i<<6)
{
myfile>>data[i];
i=i+1;
}
myfile.close();
cout<<data[0]<<"\t"<<data[1]<<"\t"<<data[2]<<"\t"<<data[3]<<"\t"<<data[4]<<"\t" <<data[5]<<"\n";
system("pause");
return 0;
}
while (i < 6)
{
myfile>>data[i];
i=i+1;
}

.txt to binary c++, issue with int

I have a text file that I am converting to binary. Its a 7 digit no. followed by a name and then repeat for however many names is listed.
1234567 First Last
7654321 First Last
Because its a 7 digit int, I am having trouble outputting it to the binary using this method with the int struct. It gives me an awfully large .DAT (binary) file whenever I write to it even with say just 3 names. Is there a better way of outputting it so my binary .dat files look about 200kb and doesn't end up in the 20mb+ range?
const int MAX = 50;
struct StudentRegistration{
int studentID;
char name[MAX];
};
fstream afile;
ifstream infile;
afile.open (fileName2, ios::out | ios::binary);
infile.open (fileName1);
while (infile >> s.studentID)
{
infile.get(space);
infile.getline(&s.name, MAX);
afile.seekp((s.studentID-1)*sizeof(StudentRegistration), ios::beg);
afile.write(reinterpret_cast <const char *>(&s), sizeof(s));
}
afile.close();
infile.close();
I removed the seekp line and it seems to do what I want to it for now.

Resources