Count numbers in text file [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am writing a simple C ++ program as my homework to count the number of numbers in a text file. Below is my code, but unfortunately it counts words and numbers. I have no idea how it should count the number of numbers, where is the error?
My text file:
lorem ipsum 5 87 451 13
My code:
#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
int main()
{
int n=0;
char plik[100], liczby[100];
string nazwapliku;
nazwapliku="file.txt";
ifstream we("file.txt");
if (!we)
{
cout<<"Can't read file'";
cin.ignore();
getchar();
return 1;
}
while (!we.eof())
{
we>>liczby;
if(we)
n=n+1;
}
we.close();
cout<<"Numbers count in "<<nazwapliku<<" : "<<n;
getchar();
return 0;
}

Let's start off with two very important things which apply to all programs you are going to write:
Never ever read unconstrained into a buffer - ever! That is the primary attack vector for hackers trying to subvert your program by overwriting what comes after buffer. Always limit the input the maximum space allowed, e.g., setting up the width of the buffer using std::setw(liczby). In nearly all cases in C++ you'd want to use std::string instead of a fixed size character buffer. These don't have problem of buffer overruns (it may still be desirable to limit the maximum amount of space they take which can be done with allocators).
Always test whether input was successful before you use the input. Doing so does not involve stream.eof() as that condition only holds when the program has exhausted all input. Also you need to check after reading (as the loop isn't written idiomatic, I didn't notice that you actually do check if (we); it is worth writing the loop idiomatic, though). For example, your loop could reasonably look like (if it weren't for the second point):
while (we >> std::setw(sizeof(liczby) >> liczby) {
// ...
}
As your program only tries to read words, it obviously only counts the number of words. To count "numbers" which seem to be sequences of digits for your assignment you'll need check whether a given word consists of only numbers (and in case you are trying to use std::isdigit() from <ccctype> please be aware that this function only accepts positive int while char is normally signed, i.e., you'd need to cast your char to unsigned char before feeding them into std::isdigit()). I leave the actual implementation as an exercise, though.

Related

Matrix of characters in c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I need matrix of characters to save 'n' subject (some subjects have 3-4 words). The user will enter 'n' number of subjects and names of subjects. I can only use CHAR, not STRING or VECTOR.
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
char matrix[n][100];
for(int i=0; i<n; i++) {
cin.getline(matrix[i][100]);
}
}
First problem with your code is that you are trying to make a variable size array with static allocation which C++ won't like (your n varies and you are trying to make char matrix[n][100]). You will need to use dynamic allocation for that.
Second problem is that getline requires an additional parameter to work (max number of characters per word you can take in, which is in your case 100).
And the third problem is that you are trying to put a whole word into a place for a single character in cin.getline(matrix[i][100]);. I'm not sure you understand why are you exactly making a matrix[n][100] so I will briefly explain.
One char stores a single character, like 'a'.
char oneCharacter = 'a';
To make a word out of those you would want few characters, so you make an array of characters. In the example I made an array of character which can take up to 5 of them.
char multipleCharacters[5];
And now you want to store a few words, so you make an array of array of characters. In the example I made an array of array of characters which can take up to 10 words of 5 characters. To make an array which size you are going to input, look up dynamic allocation from the first part of my answer.
char multipleWords[10][5];
Knowing this, can you figure out whats wrong with cin.getline(matrix[i][100]);?
As I said in a comment earlier, this is a terrible assignment. You are being asked to do several things in "odd" ways, not using and learning best practices for writing code.
My advice in general: start by separating the input, output, and "work".
Let's suppose that the code for the real lesson here is all in the "work" part. There are indeed many reasons for learning to manipulate memory this way, and C++ for writing low-level, system, or efficient code is a major part of the craft.
So, you want to arrange n words into a 2-D array of characters. Focus on (just) that, by passing in the data to be so-arranged using normal C++ code. Abstract it as a class to hold the data. Maybe this is the binary image to send to a dumb LCD on a keosk, or label printer? There may be a real reason to do something like this.
Putting in a class you can make sure memory is freed correctly; normally you want no naked new's in your code, and will use existing container types rather than low-level memory. Here, we'll use a unique_ptr of rows.
class project {
static constexpr size_t rowlen = 100;
using row = char[rowlen];
std::unique_ptr<row[]> matrix;
public:
void layout (const vector<string>& inputs);
// todo.. provide a good way to access the data
};
Now don't worry about reading from the user, especially reading directly into an odd format! That just makes this extra challenging for no reason. Take the data (presented in a normal easy-to-use way) and concentrate on doing the low-level memory manipulation chore: Allocate input.size() rows, and for each input string clamp to the maximum length and copy the characters into one row (what about the rest of the chars? Assume should be space or what?)
Clamp the length using std::max. Copy the actual characters using std::copy.
Something like this (untested; just off the top of my head):
void project::layout (const vector<string>& inputs)
{
constexpr auto N = input.size();
matrix = new row[N];
for (const size_t i= 0; i < N; ++i) {
const auto len = std::max(input[i].size(), rowlen);
auto& dest = matrix[i]; // alias the whole row
char* p= &dest[0]; // pointer to first char in the row
std::copy_n (input[i].data(), len, p);
std::fill_n (p+len, rowlen-len, ' ');
}
}
See https://en.cppreference.com/w/cpp/algorithm for details on the std algorithms. Keep that site bookmarked; it is a great way to look things up while you write code.
To do this, you need to understand how pointers work in C (and thus in C++). Also, how the same "place" can be different types: A pointer to the whole row is the same address as the first character of that row, but they are different types. So do things a little piece at a time, just as with the earlier definition of matrix.

Having lots of trouble using cin robustly in C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I can't seem to come up with a chunk of code that traps the user until it gets a positive int and prompts the user appropriately if the user accidentally types a character or random garbage like "-1-3-4-39-32xfi3/". I just need a neat failproof cin loop structure and can't figure it out. Thanks.
I'm just wondering what other people do regarding console input to make draw ideas from that..how you get around bad input.
Do this:
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
int main()
{
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
unsigned int n;
if (!(iss >> n >> std::ws) || iss.get() != EOF)
{
std::cout << "Bad input ('" << line << "'), ignoring.\n";
continue;
}
std::cout << "Success! We read: " << n << "\n";
return EXIT_SUCCESS;
}
std::cout << "Premature end of input!\n";
return EXIT_FAILURE;
}
In other words, continue reading input from the user until you are able to parse the input as the kind of data you want. I chose line-based processing, which is often the most natural, but any notion of "record" that you can skip if it isn't right will do. Note that it's possible the program never succeeds, namely if the user refuses to provide any good input.
I typically read an entire line with std::getline, then attempt to convert it to an integer with strtol. If the result is less than 0, they typed a leading -. strtol returns a pointer to the first character of input that couldn't be converted as an integer, so if it points to anything but \0, you know the user typed in something that couldn't be converted.
I really should switch to using std::stoi instead of strtol though. It supports pretty much the same capabilities, but its input is a std::string instead of a C-style string like strtol uses. I only continue to use strtol out of long habit, not because it's really a better solution.
Depending on what you have available, and how you want to respond to bad input, another possibility to consider would be boost lexical_cast. This throws an exception if it can't convert the entire input to the target type, so if you want an exception it may be more convenient (but if you don't want exceptions, it'll probably just cause you extra work).

Everytime I read in through ifstream for a specific input, the input changes, possible int overflow [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Every time I use ifstream for input to my program for large inputs, I get something weird. I have a feeling this has to do with integer overflow, but my program still doesn't work with unsigned long long. Here is a simplified version of my code that still exhibits the error:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ofstream fout ("namenum.out");
ifstream fin ("namenum.in");
unsigned long long serial;
fin >> serial;
ifstream myReadFile;
cout << serial << endl;
return 0;
}
Here is the strange input (or larger inputs):
5747867437
Here is the output I get from cout:
1452900141
I have no idea what is causing this. Any help would be awesome.
Here is advice I have hardly given ever before: always check your inputs after you attempted to read (it feels, I have given this advice only a few thousands times so it is easy to miss). The stream can't predict what you are going to read and make sure it will work:
if (fin >> searial) {
fout << serial << '\n';
}
else {
std::cerr << "failed to read the value\n";
}
Looking at your code, I'd be about 100% certain that either the file failed to open (i.e. the stream is in bad state prior to the attempt to read) or the claimed content isn't in the file.
First of all, the number you supplied is certainly within the limit of unsigned long long.
Second, using >> for unsigned long long requires C++ 11 support. C++0x supports unsigned long.
I copied your code and made a file called "namenum.in", typed "5747867437" into "namenum.in" using UTF8 encoding.
Then the output is exactly 5747867437.

C++ Programming Syntax and function assistance? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Okay so still new to the syntax of the C++ programming language and have come across a few things that are shown in examples but don't quite explain things on a level for someone to fully understand what it is.
For example if you were going to create a variable say : int x = 0; what does the zero part do, sets it to zero or holds a false value? Particullary in the code below.
Also some explanation on : if (!(cin>> input)) input = 0 if (!(cin>> 0)? if its not zero? seems like zero holds some other value.
Also cin.clear() and cin.ignore sure i've heard it clears the next line or erases something but really a thorough explanation of whats going on with this would really help?
Can't really move on to bigger things if this simply parts has holes in it.
Two other things is the endl function and cin.get() what do these do as well?
int main()
{
int input = 0;
do
{
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
if (input != -1)
{
cout<<input<<" was entered"<<endl;
}
}
while (input != -1);
cout<<"Done"<<endl;
cin.get();
return 0;
}
The code below is the code provided in the question as I write this, except I've added the requisite headers and using directive at the top:
#include <iostream>
using namespace std;
int main()
{
int input = 0;
do
{
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
if (input != -1)
{
cout<<input<<" was entered"<<endl;
}
}
while (input != -1);
cout<<"Done"<<endl;
cin.get();
return 0;
}
#include <iostream>
is a preprocessor directive. The source code preprocessor is run before the compiler proper, and performs text substitution, text inclusion and text selection. The #include directs it to include all the text from a header called iostream. The angle brackets, as opposed to double-quote characters, says that it shouldn't bother to search in the including file's directory. Well actually it's unspecified what extra search it shouldn't do, but in practice, with current compilers, it's as described.
The iostream header provides declarations of i/o stuff from the standard library, such as std::cout.
using namespace std;
makes the identifiers from the std namespace available directly in the global namespace. Meaning you can write, for example, just cout instead of qualified std::cout or fully qualified ::std::cout.
A using namespace directive is practical for small exploratory and personal tool programs, but can be more troublesome in larger code base.
Anyway, remember to NEVER put such directive in the global namespace in a header, because that's a sure way to create name collisions in code that includes that header. As an example, the standard library defines a name std::distance. Without the qualification, with a using namespace std; directive, the name distance is very likely to collide with a name distance in using code.
int main()
is the minimal declaration of main. The main function was the user-provided startup function in C, and in C++ it serves roughly the same purpose, except that in C++ dynamic initialization of static variables can happen before main is executed.
The declaration above is the C++03 way. In C++11 it can alternatively be declared as
auto main() -> int
which means exactly the same, and which is a bit more verbose, but can be reasonable to indicate a convention of using this syntax in general. I.e. for consistency.
The main function can also have arguments, which then represent the command line arguments provided to the process, but this scheme only works well in UTF-8 based *nix-es. For the main arguments are char-based, and the default char-based text encoding in Windows is such that e.g. filenames with international characters can't be represented. Thus, it's not a generally good idea to use the main arguments for portable code.
int input = 0;
declares a variable called input, of type int, and initializes it to 0.
Any zero value of a fundamental type represents false when it's used as a boolean. Conversely, any non-zero value represents true, and this convention stems from early C, which didn't have a bool type. In modern C++ it's better to use the bool type for booleans, with the values (literally) false and true.
The variable above, however, is not used as a boolean, but represents the last number input by the user.
do
{
// Stuff, called the "loop body".
}
while (input != -1);
This is a do-while loop. The continuation condition stated after the while is checked after each iteration. Which means that the loop body is guaranteed to be executed at least once.
C++ has three other loops: the while loop; the ordinary for-loop, which collects all the loop control stuff in the loop head; and the range-based for, which is especially nice for iterating over the items in a collection.
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
The first statement above just prompts the user. The cout and cin streams are synchronized, so that when the subsequent input operation is attempted, the output, if not already presented on the screen, is flushed. Instead of such automatic, implicit flushing, you can guarantee a flush by doing it explicitly, like this:
cout<<"Enter a number (-1 = QUIT):" << flush;
The expression cin >> input
attempts to interpret the next "word" of user input as an integer, and store that in the variable input, and
produces a reference to cin as its expression result.
If the input of text fails, or if the conversion from textual specification to int fails, then cin enters a failure state. In this state further input is just ignored. Happily that's easy to check for, because when a stream is used directly as an if or while (including do-while) condition, then it converts implicitly to boolean as if you had written !stream.fail().
Hence, !(cin >> input) does all of the above, and produces the result of !!cin.fail() (twice negated, “not not”), where fail is a member function that check whether the stream is in a failure state.
If the stream is in a failure state, then that state must be cleared, lest further input operations will all be ignored, and that's what
cin.clear();
achieves.
In addition there will be some input text – at the least a newline (end of line marker) – left in the input buffer, and to avoid that text being processed as valid input the next time around the loop, it should better be removed! And that's what the
cin.ignore(10000, '\n');
accomplished. Under the assumption that there's not more than 10000 characters left in the input buffer…
cout<<"INVALID" <<endl;
Outputs the text “INVALID” followed by a newline. Outputting the endl manipulator has the effect of a newline plus a flush. Thus the above is equivalent to and just short for
cout<<"INVALID\n" << flush;
It often happens that newbies are concerned with the lack of efficiency of endl as opposed to just \n. This concern is however misplaced. Iostreams are for convenience and (due to stronger type checking) avoiding the easy bugs of C style i/o; they're generally not what one would choose for efficiency.
After the loop, the
cout<<"Done"<<endl;
cin.get();
stops the program until the user enters some input.
This is because when the program is run from an IDE (as opposed to from the command line), the console window could just otherwise disappear. And especially for non-interactive programs that's undesirable. So the statement above, while not needed for this particular program, is a general convention.
However, it's ungood. It becomes very annoying when the program is run from the command line! Instead, to see all the output of a program, do either
run it from the command line, or
run it in a way that automatically stops at the end (e.g. Ctrl+F5 in Visual Studio), or
place a breakpoint at the last } right curly brace of main, and run it in the debugger.
return 0;
is unnecessary, since this is the default function result for main (main is unique in having a default function result).
The value returned from main will in practice become a process exit code.
In both Windows and *nix the convention is that 0 means success and any other value means failure.
In C++ the only portable values are 0, EXIT_FAILURE and EXIT_SUCCESS, where the latter two come from the stdlib.h header. EXIT_FAILURE and EXIT_SUCCESS depend on the system at hand, but the latter is typically just 0. In Windows you may want to use Windows' own E_FAIL instead of EXIT_FAILURE, because (for unfathomable reasons) Windows C++ compilers typically define EXIT_FAILURE as 1, which is also a specific Windows error code – and in Windows the process exit code is typically literally what that term indicates, namely a standard error code, with 0 as “no error”.

Where is the serialization going wrong? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
void insert_into_stream(std::ostream& stream, int number)
{
int length = sizeof(int);
char insert_buffer[sizeof(int)];
memcpy(insert_buffer, &number, length);
stream.write(insert_buffer, length);
}
int int_from_string(std::string string)
{
int a;
std::istringstream(string)>>a;
return a;
}
This code used to work before, I don't remember what slight change I did and it isn't working anymore.
When a number (for example, 8001) comes in, and I'm debugging just before the last statement, insert_buffer contains 'A', so obviously something is going wrong and the 2nd function doesn't retrieve 8001.
Note - I do convert the stream to a string before sending it to the 2nd function.
Where is the first function wrong?
---edit----
Yes, I was wrong, the first function is actually doing exactly what it should, the second is wrong, can anyone please fix that?
These two functions are doing completely different things.
The first function is writing out the raw binary representation of an integer to a stream.
You have just copied the bits, this is the correct thing to do if you are serialising out to a binary file.
To convert it back, you would have to read in those 4 bytes, and cast that into an integer, just like you're doing the other way round.
Of course when you examine the characters they're going to be a one byte ascii representation of the integer bits. So 'A' is a perfectly reasonable thing to be there, as is anything else as it is entirely meaningless.
The second function however, is doing an ASCII Number to Integer number conversion. i.e. atoi. This is meaningless for what you're trying to do as the characters aren't ascii numbers, they're binary integer numbers.
Edit for edit: You want something like this, just the opposite of what you did above.
int int_from_string(const char* number)
{
int a;
memcpy(&a, number, sizeof(int));
return a;
}
Try to use
stream.write((const char*)&number, sizeof(number));
It's much shorter and you can also change the type of number and it will work (For simple types).