I am new in C++. I generally program in C#, so I'm having troubles with arrays and loops. When I try to print content of dynamic array using a loop, it says corrupted requested area... For example I will give it recognize the condition used with content of array but doesn't print content of it:
// Array.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{
int size=3;
int *p;
int myarray[10];
myarray[3]=4;
p=new int[size];
p[2]=3;
if(myarray[3]==4){
cout << myarray[3] +"/n";
cout << "Why?";
}
else
cout << "Not equal " << endl;
cin.get();
delete [] p;
}
Code looks fine, unless it should be
cout << myarray[3] << "\n";
Not +
The problem is that myarray[3] +"\n".
"\n" represents the memory location of the string "\n".
You are trying to add 4 to that location and printing it. This should give you junk data or a hardware exception (resulting in a coredump) if you are accessing a protected memory location.
To get what (i think) you are asking for do,
cout << myarray[3] << '\n'
While a solution has been given:
cout << myarray[3] << "\n"
the point to get is that myarray[3] is an integer while "\n" is a string and the only way to "add" them together as strings is to first make the integer into a string. The << operator will handle the work of converting myarray[3] into a string, nothing special, and then the second << pumps a new line after it. I personally prefer code like this and find it more flexible, but it may be more that you're looking for at this stage of learning:
printf("%i\n", myarray[3]);
where printf searches for flags and loads in the other arguments as strings and outputs it in one command.
Related
I am trying to get a file path from the user in the getPath() function and return the path as a string. I am having trouble because the compiler says i need to use const char's and i dont know how to do that. How would I use const chars and what even are they. Also how do I print them to the console like in the main function.
#include <iostream>
#include <stdio.h>
#include <string.h>
char getPath() {
char path[64];
std::cout << "Input File Name For Debugging:";
gets(path);
std::cout << "Debugging: ";
puts(path);
return path[64];
}
int main(){
char path[64];
int pathlen = strlen(reinterpret_cast<const char *>(path));
//suppost to print the char array
for(int i; i < pathlen; i++){
std::cout << path[i];
}
return 0;
}
Lot's of misunderstandings
1) char is not a string, it's a character
2) An array of chars (e.g. char [64]) is not a string, its an array. It can hold a string but that's a subtly different idea
3) You don't use [64] when you mean the whole array, so return path[64]; is not the correct way to return a string.
4) Don't mix C++ I/O (std::cin, std::cout) with C I/O (puts, gets), it doesn't work reliably, Stick with C++ I/O so
std::cout << "Debugging: " << path << '\n';
not
std::cout << "Debugging: ";
puts(path);
5) You never call your getPath function so of course it doesn't execute
6) You don't initialise your loop variable i in your final loop so it has no predictable value. You should initialise i to 0
for(int i; i < pathlen; i++){
std::cout << path[i];
should be
for(int i = 0; i < pathlen; i++){
std::cout << path[i];
As you can see lots and lots of mistakes for a very short program. I'm going to show two different correct ways to write this program.
So there are two ways to represent a string in C++, there's the C++ way and there's the way that C++ inherits from C. The code you are writing above is trying to do things the C way, so I'll show that first, but actually the C++ way is much much easier. I'll show that second, but it's the way you should do things.
The first way is to use an array of characters to hold the string. But arrays have serious problems in C++. In particular it's not possible to return an array from a function, so your code above was never going to work, even if you'd fixed all the smaller problems. The way you get C++ to 'return' an array is a bit curious and I'm not going to explain it properly (you need to read a good C++ book). What you do is declare the array in the calling function and pass the array as a parameter. Here's your program written using this technique (and fixed of all the other problems).
#include <iostream>
void getPath(char path[], int n) {
std::cout << "Input File Name For Debugging:";
std::cin.getline(path, n);
std::cout << "Debugging: " << path << '\n';
}
int main(){
char path[64];
getPath(path, 64);
std::cout << path << '\n';
return 0;
}
Note I'm using getline to read the string, which is one C++ way to read a string. getline requires that you pass the size of the array it's going to read into, so I've passed that to getPath as well as the array itself.
Now for the easy way. C++ has it's own string type called std::string. You don't need to use tricky arrays at all. And the C++ string type can be returned from a function in the normal way. This makes for much more natural code. To use the C++ string type all you need to do is #include <string>. Here's your program rewritten to use the C++ string type
#include <iostream>
#include <string>
std::string getPath() {
std::cout << "Input File Name For Debugging:";
std::string path;
std::getline(std::cin, path);
std::cout << "Debugging: " << path << '\n';
return path;
}
int main(){
std::string path;
path = getPath();
std::cout << path << '\n';
return 0;
}
Notice this second program is closer to your original code, getPath has a return type, only it's std::string not char, and it has a return statement to return the path. This is the way you should be writing this code, the C++ string type will make writing string code much easier for you.
I am reading a file header using ifstream.
Edit: I was asked to put the full minimal program, so here it is.
#include <iostream>
#include <fstream>
using namespace std;
#pragma pack(push,2)
struct Header
{
char label[20];
char st[11];
char co[7];
char plusXExtends[9];
char minusXExtends[9];
char plusYExtends[9];
};
#pragma pack(pop)
int main(int argc,char* argv[])
{
string fileName;
fileName = "test";
string fileInName = fileName + ".dst";
ifstream fileIn(fileInName.c_str(), ios_base::binary|ios_base::in);
if (!fileIn)
{
cout << "File Not Found" << endl;
return 0;
}
Header h={};
if (fileIn.is_open()) {
cout << "\n" << endl;
fileIn.read(reinterpret_cast<char *>(&h.label), sizeof(h.label));
cout << "Label: " << h.label << endl;
fileIn.read(reinterpret_cast<char *>(&h.st), sizeof(h.st));
cout << "Stitches: " << h.st << endl;
fileIn.read(reinterpret_cast<char *>(&h.co), sizeof(h.co));
cout << "Colour Count: " << h.co << endl;
fileIn.read(reinterpret_cast<char *>(&h.plusXExtends),sizeof(h.plusXExtends));
cout << "Extends: " << h.plusXExtends << endl;
fileIn.read(reinterpret_cast<char *>(&h.minusXExtends),sizeof(h.minusXExtends));
cout << "Extends: " << h.minusXExtends << endl;
fileIn.read(reinterpret_cast<char *>(&h.plusYExtends),sizeof(h.plusYExtends));
cout << "Extends: " << h.plusYExtends << endl;
// This will output corrupted
cout << endl << endl;
cout << "Label: " << h.label << endl;
cout << "Stitches: " << h.st << endl;
cout << "Colour Count: " << h.co << endl;
cout << "Extends: " << h.plusXExtends << endl;
cout << "Extends: " << h.minusXExtends << endl;
cout << "Extends: " << h.plusYExtends << endl;
}
fileIn.close();
cout << "\n";
//cin.get();
return 0;
}
ifstream fileIn(fileInName.c_str(), ios_base::binary|ios_base::in);
Then I use a struct to store the header items
The actual struct is longer than this. I shortened it because I didn't need the whole struct for the question.
Anyway as I read the struct I do a cout to see what I am getting. This part is fine.
As expected my cout shows the Label, Stitches, Colour Count no problem.
The problem is that if I want to do another cout after it has read the header I am getting corruption in the output. For instance if I put the following lines right after the above code eg
Instead of seeing Label, Stitches and Colour Count I get strange symbols, and corrupt output. Sometimes you can see the output of the h.label, with some corruption, but the labels are Stitches are written over. Sometimes with strange symbols, but sometimes with text from the previous cout. I think either the data in the struct is getting corrupted, or the cout output is getting corrupted, and I don't know why. The longer the header the more the problem becomes apparent. I would really like to do all the couts at the end of the header, but if I do that I see a big mess instead of what should be outputting.
My question is why is my cout becoming corrupted?
Using arrays to store strings is dangerous because if you allocate 20 characters to store the label and the label happens to be 20 characters long, then there is no room to store a NUL (0) terminating character. Once the bytes are stored in the array there's nothing to tell functions that are expecting null-terminated strings (like cout) where the end of the string is.
Your label has 20 chars. That's enough to store the first 20 letters of the alphabet:
ABCDEFGHIJKLMNOPQRST
But this is not a null-terminated string. This is just an array of characters. In fact, in memory, the byte right after the T will be the first byte of the next field, which happens to be your 11-character st array. Let's say those 11 characters are: abcdefghijk.
Now the bytes in memory look like this:
ABCDEFGHIJKLMNOPQRSTabcdefghijk
There's no way to tell where label ends and st begins. When you pass a pointer to the first byte of the array that is intended to be interpreted as a null-terminated string by convention, the implementation will happily start scanning until it finds a null terminating character (0). Which, on subsequent reuses of the structure, it may not! There's a serious risk of overrunning the buffer (reading past the end of the buffer), and potentially even the end of your virtual memory block, ultimately causing an access violation / segmentation fault.
When your program first ran, the memory of the header structure was all zeros (because you initialized with {}) and so after reading the label field from disk, the bytes after the T were already zero, so your first cout worked correctly. There happened to be a terminating null character at st[0]. You then overwrite this when you read the st field from disk. When you come back to output label again, the terminator is gone, and some characters of st will get interpreted as belonging to the string.
To fix the problem you probably want to use a different, more practical data structure to store your strings that allows for convenient string functions. And use your raw header structure just to represent the file format.
You can still read the data from disk into memory using fixed sized buffers, this is just for staging purposes (to get it into memory) but then store the data into a different structure that uses std::string variables for convenience and later use by your program.
For this you'll want these two structures:
#pragma pack(push,2)
struct RawHeader // only for file IO
{
char label[20];
char st[11];
char co[7];
char plusXExtends[9];
char minusXExtends[9];
char plusYExtends[9];
};
#pragma pack(pop)
struct Header // A much more practical Header struct than the raw one
{
std::string label;
std::string st;
std::string co;
std::string plusXExtends;
std::string minusXExtends;
std::string plusYExtends;
};
After you read the first structure, you'll transfer the fields by assigning the variables. Here's a helper function to do it.
#include <string>
#include <string.h>
template <int n> std::string arrayToString(const char(&raw)[n]) {
return std::string(raw, strnlen_s(raw, n));
}
In your function:
Header h;
RawHeader raw;
fileIn.read((char*)&raw, sizeof(raw));
// Now marshal all the fields from the raw header over to the practical header.
h.label = arrayToString(raw.label);
h.st = arrayToString(raw.st);
h.st = arrayToString(raw.st);
h.co = arrayToString(raw.co);
h.plusXExtends = arrayToString(raw.plusXExtends);
h.minusXExtends = arrayToString(raw.minusXExtends);
h.plusYExtends = arrayToString(raw.plusYExtends);
It's worth mentioning that you also have the option of keeping the raw structure around and not copying your raw char arrays to std::strings when you read the file. But you must then be certain that when you want to use the data, you always to compute and pass lengths of the strings to functions that will deal with those buffers as string data. (Similar to what my arrayToString helper does anyway.)
I'm totally new to programming and heard that C++ or the Assembly Language is a good startning point for someone that want to understand what happens under the hood. I want to follow this follow through even though some of you might have other suggestions. I've been an active student for a week now and for my second challange my teacher asked us to write a cypher. Nothing fancy, but something that scrambled and unscrambled the string written by the user. So far I've tried to scramble them for starters since I deduce that if I'll solve that problem, the unscramling will be achieved through a similar process. I know there's plenty of snippets of code out there already, but I'm really intressted and want to learn through the trial and error method, based on my own assumptions.
I would appriciate it greatly if someone could point out why I get the message: "Terminate called after throwing an instance of 'std::out_of_range'
#include <iostream>
#include <string>
using namespace std;
string latSorted {"abcdefghijklmnopqrstuvwxyz ,."};
string latUnstorted {"-_qazwsxedcrfvtgbyhnujmikolp"};
int main() {
cout << "\n -----------------------------------------------" << endl;
cout << " Enter some text: ";
string usrText;
string* p_usrText; // Pointer Initialization
cin >> usrText; // User enter text
p_usrText = &usrText; // Memory allocation gets assigned to the pointer variable
cout << " You've entered " << *p_usrText << endl << endl;
for (size_t i=0; i < latSorted.length(); i++)
{
char searchChar = latSorted.at(i);
char cryptChar = latUnstorted.at(i);
for(size_t j=0; j < usrText.length(); j++)
{
if(usrText.at(j) == searchChar)
{
*p_usrText = usrText.replace(usrText.begin(), usrText.end(), searchChar, cryptChar); // Memory allocation is still within range due to the pointer. Should not say "out of range".
}
}
}
cout << ' ' << usrText << endl;
cout << endl;
return 0;
}
Thx//Alle
It appears that latSorted and latUnstorted are different lengths.
char cryptChar = latUnstorted.at(i);
Would result in the exception for the last value of i.
I have finished writing a program that included reversing, expanding and shifting arrays using the pointer requirement asked by the professor. Everything compiles but the answer from the expand function does not return what I wish: adding 0s after the old user input array which asks for the size of the array and the numbers you wish to put into the array. I think my problem may lie from the fact that I include a pointer on something that might not have a reference in the program. Below is my code:
// *numPtr refers to my old user input array and int tamaño is the size of the array
void expandArray(int *numPtr, int tamaño) {
int *nuevoArray = new int[tamaño *2];
for (int i = 0; i<tamaño; i++) {
nuevoArray[i] = numPtr[i];
}
for (int i = tamaño; i < (tamaño*2); i++) {
nuevoArray[i] = 0;
}
std::cout << nuevoArray << " ";
}
As I said, my theory of the code not compiling the way I wish is because I use the *nuevoArray and it has no reference in my main code, but then again, I am just a beginner with C++. I was thinking of just doing a vector, but I think I would not follow the pointer requirements placed by the professor.
If you want to print the contents of nuevoarray, just use a for loop like this:
for (int i = 0; i < (tamaño*2); i++) {
std::cout << nuevoArray[i] << " ";
}
std::cout << "\n";
Also, since you are using new[] to create the array, you should not forget to delete[] it!
you can print your array by using
for (int i = 0 ; i < tamano * 2 ; ++i) {
std::cout << nuevoArray[i] << " ";
}
std::cout << std::endl;
or in c++11
for (auto i : nuevoArray) {
std::cout << i << " ";
}
std::cout << std::endl;
PS: The std::endl will return to the start of the new line and flush the cout buffer.
Your code does appear to be allocating a larger array and correctly copying data from numPtr into the new array and also correctly filling the remainder of the new array with zeros.
You don't explicitly say what you expect this function to output, but I'm guessing you expect it to print out the contents of the new array, and that you believe there's a problem because instead of that, you're seeing it print something like "0x7fb46be05d10".
You're not correctly printing the array out. Instead you're printing the memory address of the first element out. If you want to see the contents, then you need to loop over the elements of the array and print each one out individually.
Here's a function showing one way of doing that:
#include <algorithm>
#include <iterator>
void printArray(int *arr, int n) {
std::copy(arr, arr + n, std::ostream_iterator<int>(std::cout, " "));
}
Now you can replace the line std::cout << nuevoArray << " "; in your existing code with printArray(nuevoArray, tamaño*2);
(Also it sounds like whoever is teaching you C++ should take a look at this presentation from the recent C++ conference, CppCon 2015: Stop Teaching C)
I have the following program, which is storing four strings in map and printing first time. Now its running the another time to retrieve the stored values. But the second resutls are not same as first time results.
#include <map>
using namespace std;
void fun_call(void **,char * );
main(){
void *data=NULL;
char value[100];
int i=0,j=0;
char key[][10]={"disk1","disk2","disk3","disk4"};
cout << "printing all mapped values " << endl ;
data = (void *) malloc( 100);
for(j=0;j<2;j++){
for(i=0;i<4;i++){
fun_call(&data,key[i]);
memcpy(value,data,100);
cout << "key ="<<key[i]<<" value is " << value << endl;
}
cout <<"====================="<< endl;
}
}
void fun_call(void **tmp,char name[10])
{
void *tmp_data;
char str[100]="ravindra";
int len =0;
static std::map<std::string,void *> name_data_map;
std::map<std::string,void *>::iterator iter ;
iter=name_data_map.find(name) ;
if ( iter == name_data_map.end())
{
len=strlen(str)+strlen(name)+1;
tmp_data = (void *) malloc ( len );
strcat(str,name);
memcpy(tmp_data,str,len);
name_data_map[name]=tmp_data;
cout << "Inside the if" << endl ;
}
else
cout << "disk pos "<< iter->first << endl;
cout << "Outside the if" << endl ;
iter=name_data_map.find(name) ;
memcpy(*tmp,iter->second,len);
}
Output:
$ ./a.out
printing all mapped values
Inside the if
Outside the if
key =disk1 value is ravindradisk1
Inside the if
Outside the if
key =disk2 value is ravindradisk2
Inside the if
Outside the if
key =disk3 value is ravindradisk3
Inside the if
Outside the if
key =disk4 value is ravindradisk4
=====================
disk pos disk1
Outside the if
key =disk1 value is ravindradisk4
disk pos disk2
Outside the if
key =disk2 value is ravindradisk4
disk pos disk3
Outside the if
key =disk3 value is ravindradisk4
disk pos disk4
Outside the if
key =disk4 value is ravindradisk4
any idea why the second iteration is giving all data as : "ravindradisk4"
len is set to 0 in the beginning of fun_call, so if in the second run it doesn't go into your if, memcpy copies 0 bytes in the end. So the last value in main() from the first iteration remains the same regardless of key.
There are a lot of things wrong with your code, if it is intended to be a valid (or remotely idiomatic) C++ program.
As #starbugs points out, you're not using the right length the second time through to copy your result out. The one-line "fix" would be to change:
memcpy(*tmp,iter->second,len);
...to:
memcpy(*tmp,iter->second,strlen((char*)iter->second)+1);
For some basics on why brittle C string techniques are best replaced with C++ methodology, I like to show people this:
Learning Standard C++ As A New Language (PDF) by Bjarne
Once you've grasped that you might be more able to embrace the spirit in which C++ and the standard library should be used.
Your program is so trivial that it's easy to show how it can be simplified to produce idiomatic code which is far more robust and easy to read:
#include <map>
#include <iostream>
#include <string>
using namespace std;
string fun_call(string name)
{
static map<string,string> name_data_map;
map<string,string>::iterator iter;
iter = name_data_map.find(name);
if (iter == name_data_map.end()) {
string mapvalue = "ravindra";
mapvalue += name;
name_data_map[name] = mapvalue;
cout << "Inside the if" << endl ;
}
else
cout << "disk pos "<< iter->first << endl;
cout << "Outside the if" << endl;
iter = name_data_map.find(name) ;
return iter->second;
}
int main() {
string keys[] = {"disk1","disk2","disk3","disk4"};
cout << "printing all mapped values " << endl ;
for(int j = 0; j < 2; j++) {
for(int i = 0; i < 4; i++){
string value = fun_call(keys[i]);
cout << "key =" << keys[i] <<" value is " << value << endl;
}
cout << "=====================" << endl;
}
}
I'll stop there at providing a basically equivalent program with the same output and control flow.
Notes:
In standard C++, main must have an int as the return type (though it doesn't need arguments or a return statement, oddly enough)
The using namespace std; line frees you from having to type std:: in front of things in front of standard library classes like string, map, and their iterators. But don't put that in header files because it can cause problems with other source files that include them and have their own definitions which might conflict with the standard names when not disambiguated.
If you use the standard library then value types do their memory management under the hood, and the memory they use is allocated inside the class and freed in the destructor. Should you ever need to do explicit memory management then use new and delete.
First off, in general, in C++ consider using new/delete instead of malloc()/free().
I am not sure what you are exactly trying to accomplish (i.e. why you continuously copy values) but you have no length set so memcpy() doesn't copy anything.
Another simple fix to this issue is to use the pointer stored in iter->second (note that you would be able to modify data then and update that map entry - so perhaps this is not what you want).
For instance, do not allocate memory for your data variable in main and simply change this line
memcpy(*tmp, iter->second, len);
to
*tmp = iter->second;
Now the pointer address of data in main is set to the pointer address stored in the map.
First of all, I'm not even sure how your code compiles. Your main function lacks a return type and void/no-return is just bad practice. Restructure it to accomodate a simple return of 0 and make its return type int.
Furthermore, several includes are lacking before it even compiles (namely, iostream and string). Instead of using using namespace std, try to "pull" only the things you need from the std namespace. Bringing it all in is a potential hazard and bad practice in general, because you might encounter naming convention collisions in the future (and that will bring forth lots of headaches).
Back to the issue at hand. You're, if you're not experimenting/punishing your mind, applying some very bad practices here. This much memory-copying and pointer shifting around I don't get to do even while I'm working with moving vertex buffers around. And match your allocations with deallocations, that's some very bad memory management. And in C++, we use new/delete.
Since you're passing in the address of the pointer to the data variable, you can simply modify data's pointer by using *tmp.
Since your name_data_map is static, it survives the loop. Therefore, the second data member of the iter is the actual pointer to the data object at hand. Simply change the last line of code of your second function:
*tmp = iter->second;
Anyways, that's my two cents... I don't even get what you're trying to do. Good luck!