Printing a character array - c++

I have a function print_string which takes in a character array as its argument.
For some reason I can't get it to print out if I use a while loop like
int i = 0;
while(str[i]!= '\0'){
cout << str[i];
i++;
}
but if I use a for loop and specify the length of the array it can.
Thanks

The code works for me. My guess: you're probably experience the problem with buffering. std::cout is buffered, so characters first go into buffer, and then, at certain points, the contents of the buffer are put on screen.
The most typical way to force this is: std::cout << std::endl;
Also, tip: std::cerr is unbuffered, so you could use it for debugging this issue.

Related

Printing array elements in one second intervals using sleep()

I have an array that contains chars.
I am trying to print out an element once every second.
int i=0;
while (i< 110)
{
cout << arrayValue[i]<<"\0";
sleep(1);
i++;
}
This for some reason just waits for 110 seconds and than prints out the whole array at once.
But if i add a new line after every element it works just fine
int i=0;
while (i< 110)
{
cout << arrayValue[i]<<"\0";
cout<< endl;
sleep(1);
i++;
}
Any recommendation on how to get each element to print chronologically without having to make a newline?
This for some reason just waits for 110 seconds and than prints out the whole array at once.
Actually it doesn't, but your output is buffered. There is buffering in the C++ stream object, in the OS data pipe, and in your terminal.
Your stream thinks it would be a waste of resources passing characters through one at a time, and it's kind of right: the stream doesn't know you have a second to wait in between each one.
You don't need the newline, though; you can basically force a flush like so:
std::cout << std::flush;
Recall that std::cout << std::endl is equivalent to std::cout << '\n' << std::flush, and it's the '\n' part that you don't want.
This is usually enough but you may also need to reconfigure your terminal to turn off line buffering. (That's unlikely for output but quite common for input).

Accessing data inside an array via pointer error

I have 2 files in msg format. msg format is not important here.
car.msg
int speed;
int width;
cararr.msg
car mycar[];
I want to print all the information about all the cars that are present but I have no clue about the number of cars present(how big is the array) so I use the following technique to print the information.
so I do this:
cararr* ptr2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << ptr2car->mycar[i].speed <<endl;
cout << ptr2car->mycar[i].width <<endl;
}
Despite this, I am receiving errors. I do not know what did I do wrong. I have no clue what approach should I use to get this output. please Help
Also why should I take a pointer to cararr, when I can just take an instance of cararr inst2car and do something like this:
cararr inst2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << inst2car.mycar[i].speed <<endl;
cout << inst2car.mycar[i].width <<endl;
}
thanks
In general you need to know exactly what's at the end of the array. You need some sort of sentinel value to use as a delimiter to indicate the end of the array.
'\0' used in c strings is an example of such delimiter.
You need to ensure the last element in the array is such delimiter and check for it in the condition.
It's hard to give you more specific answer with such generic question.
For example, if you knew the last element will have speed -1, you can use that:
for(int i=0;mycar[i].speed != -1; i++) {

odd output from char array

I am currently writing a command line "parser" so to speak, and so far it has been working until I tried a few ways to add options/parameters.
void parser::nextCom() {
cout << parser::prompt; // parser::prompt = "> "
string com;
getline(cin, com);
char the_command[5]; // i want this to store the command e.g. "go" given that go is a command
for (int i = 0; i < com.size(); i++) {
if (com[i] == ' ') break;
else the_command[i] = com[i];
}
cout << the_command << endl;
}
The command is copied but some very unwanted characters show up when in print the_command to the console.
This is what I get if I pass "go north" as a command:
goÌÌÌÌÌÌÌÌÌÌÌÌÌÌØNi
I am not too sure about char arrays in C++, but I don't know how I am getting this output. Any help at all will be appreciated. Any questions about the code or if you need more of my code, just comment, thanks in advance
cout << the_command << endl;
When you print a char array like this, characters continue to be inserted until the null character \0 is found in the string.
Before you start copying characters from com to the_command, the array is completely uninitialized. I'll represent these unknown characters with question marks (but of course, they're probably not actually question marks):
? ? ? ? ?
This means you have no idea what the values of the chars in the array will be. You then copy only the characters g and o from the_command into com, so your array now contains:
g o ? ? ?
So when you attempt to output this array, the output stream doesn't know when to stop. You need to make sure you insert an \0 after the o. One way to do that would be:
for (int i = 0; i < com.size(); i++) {
if (com[i] == ' ') {
the_command[i] = '\0';
break;
}
else the_command[i] = com[i];
}
This will leave the array like so:
g o \0 ? ?
However, you'd be much better off just sticking to std::string. I don't want to think about the trouble you'll have with this array that could just be avoided. Here's how I would write your function:
void parser::nextCom() {
std::cout << parser::prompt;
std::string command_line, command;
std::getline(cin, command_line);
std::stringstream command_line_stream(command_line);
command_line_stream >> command;
if (command == "go") {
std::string direction;
command_line_stream >> direction;
go(direction);
}
}
You're not null-terminating the_command after the last character is read. Or doing any bounds checking.
Please, use std::string instead.
Change the code to:
if (com[i] == ' ')
{
com[i] = '\0';
break;
}
This will ensure there is a null terminator at the end of your char array. The reason you are seeing garbage is because std::cout will happily print characters until it sees a null terminator.
this is because you have a buffer overflow in your code. you copied an indeterminate length string into a char[5] buffer... basically, your loop is copying as many bytes as determined by the input string, into past the end of the char[5] array, which is no longer null terminated, so "cout" is just reading until it finds null bytes.
Basically the_command[5] contains garbage since is not initialized and doesn't contains the character terminator. You can clear it first, and you'll be fine
for (i = 0; i < 5; i++) {
the_command[i] = 0;
}

C++ binary file reading into struct

I have written a binary file using a struct as follows:
struct block{
char data[32];
};
so what I end up with is basically a large binary file full of char[32]. The data is formatted in specific positions so grabbing specific pieces of information is not difficult. However, I tried to read the file like so:
int lines=0;
std::ifstream inputFile("file.bin",std::ios::binary);
while (!inputFile.eof())
{
inputFile.read(blocks[lines].data, sizeof(block));
lines++;
}
inputFile.close();
lines--;
and then displaying it like this:
std::cout<<"block 1: "<<blocks[0].data<<std::endl;
// etc ...
I thought that blocks[i].data should just give me the char[32] that belongs to index i, but it instead gives me every "data" element in the struct from that index to the end of the struct. I'm sure that it is my misunderstanding of how that works. My question is: how do I just get the char[32] represented by blocks[i].data?
The problem is your std::cout output statement. When you try to output blocks[0].data, what operator<< gets is not the array of 32 chars, but a pointer to the first char. This is interpreted as pointer to a C string, and therefore it outputs all characters found in memory from there on until it finds a '\0'. Since each array element contains just the corresponding characters from the file, all characters of the file are output (unless there's a '\0' in the file, then output stops there). Also, you seem to be (un-)lucky that a '\0' follows your data in memory, so the output stops there (instead of continuing to output whatever is in memory afterwards, and possibly giving a segmentation fault when the end of the process' memory is reached).
To just output the 32 charactes as characters, use std::cout.write(blocks[0].data,32). Otherwise to output them as ints just loop through them and convert each one to int:
for (int i = 0; i < 32; ++i)
std::cout << static_cast<int>(blocks[0].data[i]) << ' ';
Of course you can use all the stream manipulators to get the numbers in the form you want (e.g. std::hex for hexadecimal output, and/or std::setw and std::setfill to get fixed width numbers).
std::cout<<"block 1: "<<blocks[0].data<<std::endl;
You're sending a char[] to the stream, which gets promoted to a char*, so it thinks it's a NULL terminated string, and attempts to display it as such. It's hard to tell what it is that you want, but this will display it in hexidecimal:
std::cout << std::setfill('0') << std::hex;
for(int i=0; i<25; ++i)
std::cout << std::setw(2) << blocks[0].data[i];
std::cout << std::setfill(' ') << std::dec;
Your input section needs to be changed:
while (inputFile.read(blocks[lines].data, sizeof(block))
{
lines++;
}
The reason is that the EOF condition is not determined until AFTER a read operation occurs. One side effect of your use of EOF checking is that an extra line may be read.

C++, Text to ASCII while-loop error

I've come this far without asking for help, but I've got a problem that I can't seem to fix. I like cryptology, so now that I am learning C++, I want to make programs to encrypt and decrypt strings. I read that the best way is to convert the text to ASCII and go from there, so here is a simple program I made in C++ to try and convert a char variable to ASCII:
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int main()
{
char strString[1000];
cout<<"Enter you message:"<<endl;
cin>>strString[1000];
string strEncrypt;
int a = 0;
while (strString != '\0')
{
int b = (int)strString[a];
strEncrypt.at(a) = b; //This is where I'm getting an error.
a++;
}
cout<<"Encrypted message:"<<endl;
cout<<strEncrypt<<endl;
}
So, I've tried all 3 things I know to do to troubleshoot (Google, check for missing simicolons, and make sure I'm doing == not =, but this is just something I don't know how to do, not something I'm forgetting (I hope). So, any help would great!
You don't have to change the characters to ASCII they already are. Chars are basically the same as integers in memory.
Now to your question; . If you want to set a character in a string you can do that like this
string[index] = b;
Another thing to be careful for in your code. You are using cin to read the string from the user. This will not let you read messages that have spaces in them and will only read the first word. For example, if the user enters "Love Crypto" cin will only read "Love" and "Crypto" will be ignored. To get the entire line, use getline instead.
As for looping over characters in a string, it's better to do it as follows:
for(int i = 0; i < strString.length(); i++)
{
strString[i] = bla;
}
Again, you're code isn't actually doing anything. It is only reading a letter and then storing a "letter" in another string.
string::at() throws exception if the index passed to at() is out of range. So, if you are getting runtime error then it's expected. Because, your string strEncrypt is initialized to "" and thus the size is 0.
You may try
strEncrypt.reserve(strlen(strString));
Easiest way to actually make the code you have work is change this line strEncrypt.at(a) = b; to this strEncrypt += b; Which will add the characters to the empty string strEncrypt.
Your code doesn't make much sense though as char types are already ascii. You'll have to explain more about what kind of encrypting you are trying to do and maybe we can point you in the right direction.
EDIT: After thinking about what you're trying to do a bit more based on the code you have it seems like you want to print the numeric ascii value of characters. You can do that with just a cast like this:
string input;
cout << "Enter you message:" << endl;
// handle spaces in the message
getline(cin, input);
cout << "String chars as ascii values:" << endl;
cout << "Char: " << "ASCII Code:" << endl;
for (int i = 0; i < input.length(); ++i)
{
// casting the char to an int with (int) will print the ascii code
cout << input[i] << " " << (int)input[i] << endl;
}
On top of the fact that your input is already in ASCII, keep in mind that doing cin >> strString[1000] doesn't limit the input captured to the length of your buffer unless you specifically specify the number of characters to capture for the stream object using setw() or setting it's ios_base::width data member. So your method right now risks buffer overflows.
Secondly, the form of cin >> that you're using will not capture the entire line of input. Instead it will stop at the first white-space or any other delimiting character (or end-of-file if that is reached first). In your case, if you are entering a line like "Hello World", then the syntax you're using will only capture "Hello" and drop "World".
A much better idea would be to use the getline() function with a std::string object if you are wanting to capture a line of input to a string and remove the delimiting newline character without risking buffer overflows ... for instance:
string strString;
getline(cin, strString);
Apart from advises given, when receiving this kind of run-time errors use Cppcheck utility.
It will give you the answer: "Message: Array 'strString[1000]' index 1000 out of bounds".