Pointer to a C-String? [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 7 years ago.
Improve this question
For an intro to CS assignment, I am writing a C++ program in Visual Studio 2010 which returns an integer and accepts a pointer to a C-string as an argument. I know that I need to make a function besides an int main to succeed, but I am not exactly sure about how to initialize a char pointer array which points to a predefined char array, if possible.
The purpose of this program is to get a comment from a user within a predefined limit then inform said user how many characters (including whitespace) that comment is.
The error is: a value of type "char" cannot be assigned to an entity of type "char *";
Here is my program that does not compile:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
//function protoype
void evalStr(char arr[]);
//variable
int length;
//main function
int main()
{
const int SIZE = 201;
char arr[SIZE];
char *str[SIZE];
cout << "Please enter a comment under " << (SIZE - 1) << " characters to calculate it's length: ";
*str = arr[SIZE];
cin.getline(arr, SIZE);
length = strlen(*str);
evalStr(arr);
system("PAUSE");
return 0;
}
//function defintion
/* get the string
count the number of characters in the string
return that number
*/
void evalStr(char arr[])
{
printf("The length of the entered comment is %d characters\n", length);
}
If there is a general method to utilizing char pointer arrays or perhaps pointers to strings, this code could be redone to return the value of the string instead of utilizing that printf statement. What all am I doing wrong?
Edit: Here is an updated version of this program that compiles, runs, and informs the user if the character limit is reached or exceeded.
// Accept a pointer to a C-string as an argument
// Utilize the length of C-string in a function.
// Return the value of the length
// Display that value in a cout statement.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
//variables
const int SIZE = 201;
int length;
char arr[SIZE];
char *str;
//main function
int main()
{
str = &arr[0];
// Size - 1 to leave room for the NULL character
cout << "Please enter a comment under " << (SIZE - 1) << " characters to calculate it's length: ";
cin.getline(arr, SIZE);
length = strlen(str);
if (length == (SIZE - 1))
{
cout << "Your statement has reached or exceeded the maximum value of "
<< length << " characters long.\n";
}
else
{
cout << "Your statement is ";
cout << length << " characters long.\n";
}
system("PAUSE");
return 0;
}
//function defintion
/* get the string
count the number of characters in the string
return that number
*/
int countChars(int)
{
length = strlen(str);
return length;
}

Let's talk about what is happening in main instead:
int main()
{
Okay, so you're going to have strings of 201 characters. Seems reasonable.
const int SIZE = 201;
And you've declared an array of 201 characters:
char arr[SIZE];
And now you declare an array of 201 pointers to characters. I'm not sure why you would want to do that. I suspect you think this does something other than what it actually does:
char *str[SIZE];
This is reasonable (except "it's" means "it is", but you want the possessive version, "its"):
cout << "Please enter a comment under " << (SIZE - 1) << " characters to calculate it's length: ";
This assigns the 201st character to the first character pointer in your array of char pointers. This is an error because:
arrays are zero-indexed, so the 201st character (when you start counting at zero) is beyond the end of the array.
you haven't initialized the memory in arr to anything yet.
you're assigning a char to a char *.
So, given the above I'm not sure why you're doing this:
*str = arr[SIZE];
This looks reasonable:
cin.getline(arr, SIZE);
This is an error because str doesn't point to memory that contains a valid string at this point.
length = strlen(*str);

When you "point to a string", actually you point to the first character of the string. The end of the string can be found by looking at successive memory locations until you find a location containing a null byte. So your code should be:
char *str; // can point at a character
// ....
str = &arr[0]; // point to the first character of arr
// ....
length = strlen(str);

Related

Char outputting random characters at the end of the sentence

#include <iostream>
#include <string.h>
using namespace std;
void crypt(char* sMsg)
{
cout << "Original Message: '" << sMsg << "'" << endl;
int length = strlen(sMsg);
char sMsg_Crypt[3][length];
/* sMsg_Cryp[3]
[0] CRYPT LETTERS, ASCII + 3
[1] INVERT CHAR
[2] HALF+ OF SENTENCE, ASCII - 1
*/
for (int i=0; i<length; i++)
{
if (isalpha((int)sMsg[i]))
sMsg_Crypt[0][i] = sMsg[i] + 3; // DO ASCII + 3
else
sMsg_Crypt[0][i] = sMsg[i];
}
cout << "Crypt[0]: '" << sMsg_Crypt[0] << "'" << endl;
}
int main()
{
char sMsg[256];
cin.getline(sMsg,256);
crypt(sMsg);
return 0;
}
Input:
Hello World! Testing the Cryptography...
Output:
Original Message: 'Hello World! Testing the Cryptography...'
Crypt[0]: 'Khoor Zruog! Whvwlqj wkh Fu|swrjudsk|...Çi­o'
Why this Çi­o is comming out??
For starters variable length arrays like this
int length = strlen(sMsg);
char sMsg_Crypt[3][length];
is not a standard C++ feature.
You could use at least an array of objects of the type std::string like for example
std::string sMsg_Crypt[3];
Nevertheless the problem is that the array sMsg_Crypt[0] dies not contain a string. That is you forgot to append inserted characters in the array with the terminating zero character '\0'.
You could write after the for loop
sMsg_Crypt[0][length] = '\0';
provided that the array (if the compiler supports VLA) is declared like
char sMsg_Crypt[3][length+1];
Firstly, you can't define a static char array like this: char sMsg_Crypt[3][length];. That is because the length is not a const type, meaning the size of the array will be sMsg_Crypt[3][0] (this is because the size is not known at compile time). In MSVC, it'll flag an error (by IntelliSense). Since you know the size beforehand (256), you can replace the length with 256.
The second fact is that you're using C++ and you have access to std::string. So without using a char buffer, use std::string instead. It would look something like this: std::string sMsg_Crypt[3];
The last fact is that, for a string to be read correctly, it needs to be null-terminated ('\0' at the end). This means that the ending character must be '\0'. In the case of std::string, it does it for you.

Using pointers to find positions of characters between unbalances parentheses

I am given a C++ programming problem: In a string I need to find wether or not there are balanced parentheses. If not, using pointers I should find position of the characters between unclosed parentheses (between second opening and nearest closing).
The problem statement is a bit confusing, I know. I think it should work somehow like that:
Input #1:
((aba)aaab)
Output:
OK.
Input #2:
(aa(a)ab
Output:
Parentheses not balanced: between characters 1 and 6.
Code below solves part of problem with the closed parentheses check and also there is a structure to keep the address of the opening parenteses. I am not sure how exactly to use pointers for that purposes, some attempts did not give any result, so I need some help here.
#include<iostream>
#include<string>
#include<stack>
using namespace std;
struct br_data{
char br_t;
char *cptr; //store the address of the opening parenthesis
};
int main (){
string input;
int addr;
br_data br;
getline(cin, input);
stack<br_data> braces;
char *a = input[0];
auto init_char = static_cast<void*>(&a); //store the address of the first character in the input string
cout << static_cast<void*>(&a) << endl; //gives the address in memory
for(auto c: input) {
if (c == '(') {
br.br_t = c;
br.cptr = &c; //storing the address of the first parenhesis
braces.push(br);
} else if (c == ')' ) {
if (braces.empty())
cout << "This line does not contain unclosed parentheses\n";
if (!braces.empty())
braces.pop();
}
}
if (!braces.empty()){
//int addr = br.cptr;
cout << "This line does not contain unclosed parentheses\n";
//int pos = (&br.cptr) - (&a); //how to calculate the position??
cout << "Position of the second opening parenthis is " << () << endl;
//cout << "Position of the nearest closing parenthis is " << -how?? (static_cast<void*>(&br.cptr)) << endl;
}
if (braces.empty()){
cout << "Parentheses are balanced in this line\n";
}
return 0;
}
When you write
br.cptr = &c; //storing the address of the first parenhesis
you're actually storing the address of a local object of char type declared earlier:
auto c: input
By the moment you exit the loop it is officially dangling.
One simplest solution would be to actually consider string's characters, not their local copies:
for(auto &c: input) {
(and, even better, change auto into char for better clarity keeping source length the same). Then you can go on and see how your solution needs to be fixed further.
(A few extra free advice: input[0] is a rvalue reference of type char so it makes no sense to assign it to a variable of type char *, and what you try to do in that line is actually written as char *a = input.c_str(); or input.data() or even &input[0], pick the best option; and br.cptr is of type pointer-to-char already, so the character's position in a string would be calculated as br.cptr - a, you need to subtract the pointers themselves, not their addresses.)
#include <iostream>
using namespace std;
int main(){
char str[]="Hello Programming";
char *ptr;
char ch;
char s;
s='n';
ptr=str;
cout<<"To be found Character"<<endl;
cin>>ch;
while(*ptr++ != '\0')
if(*ptr==ch)
s='y';
if (s=='y')
cout<<"FOUND";
else
cout<<"not found";``
return 0;
}

The last characters in my C-style string are odd values when I

for our assignment we have to work with C-style strings in C++, and reverse an input, however when I have a string of 6 or more characters it outputs the reversed string as well as some garbage values. Any help for fixing this is appreciated.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 11;
char name[SIZE];
cout << "Please enter a name of 10 characters or less ";
cin.getline(name, SIZE);
char *stringStart, *stringEnd;
stringStart = name;
stringEnd = &name[strlen(name)-1];
char backwardsName[SIZE];
int i = 0;
// Appending each element to backwardsName starting with last character from name and decrementing.
while (stringEnd >= stringStart)
{
backwardsName[i] = *stringEnd;
++i;
--stringEnd;
}
cout << backwardsName << endl;
return 0;
}
I have tried using pointers to even ending the backwardsName string with a NULL character '\0' to no avail. The pointers did the same thing. The NULL character did help, but it started to break down when strings were 8 or more characters (I think).
The issue is with NUL termination. You did not put a \0 after reversing backwardsName.
backwardsName[i] = '\0';
cout << backwardsName << endl;

passing array as parameter to a function

this script is supposed to output array values that were inputted by the user into array "store." I am trying to store all the char array values into string temp. I get the error on line 12: "[Error] invalid conversion from 'char*' to 'char' [-fpermissive]." Would appreciate any help!
Edit: so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so? The cmd only correctly couts the first string but after the space, it messes up.
#include <iostream>
#include <cstdlib>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50];
cout << "enter text: " << endl;
cin >> store;
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Using input from all answerers I finally got the fixed code:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50] = {0};
cout << "enter text: " << endl;
cin.getline(store, 50);
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max && store[i]!=0)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Thanks everyone. i learned a lot!!!
When you get an input using "cin" your input automatically ends with 0 (NULL).
You just need to add one little piece of code to your while statement.
instead of this :
while (i < max)
use this :
while (i < max && store[i]!=0)
Now it will stop when the input string is finished and won't print any garbage existed in the array beforehand.
To show that cin does add terminating zero, i initialized the array to 46, and put a breakpoint after the cin
so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so?
Not sure what you mean by jumbled up. But since you did not tell us what you typed its hard to know it looks like it worked to me:
> ./a.out
enter text:
Plop
Plop�ȏU�
Notice that since my input is only 4 characters long. This means that a lot of the characters in the array still have undefined (ie random values). This is why I am seeing junk. To get past this initialize the array to have all 0 values.
char store[50] = {0};
Even bettern use a C++ object than handles longer strings.
std::string store;
std::getline(std::cin, store);
Note: passing arrays to functions by value is not a good idea. On the other end they have decayed to pointers and thus do not act like arrays anymore (they act like pointers whose semantics are similar but not identical).
If you must pass an array pass it by reference. But I would use a C++ container and pass that by reference (it is much safer than using C constructs). Have a look at std::string
The declaration of the function is wrong. Should be void coutArray(char *, int);
Look at the Implicit Conversion rules to understand what the compiler can do and what it cannot to do for you.
The issue with your program was that you were probably entering in less characters than the maximum size of the buffer. Then when you passed the maximum size as the parameter to coutArray, you assigned unfilled slots in the char array to temp. These unfilled slots could contain anything, as you have not filled them up to that point.
Your program is still correct, but what would be better would be to use read so that the number of bytes you specify is the minimum number of bytes that can be entered:
std::cin.read(store, 50);
Even better solution would be to use std::string:
std::string store;
std::cin >> store;
// or for the entire line
std::getline(std::cin, store);
It also follows that your coutArray should be changed to:
void coutArray(std::string);
// ...
void coutArray(std::string str)
{
std::cout << str << std::endl;
}
Look at this way
template<typename T, size_t N>
void MyMethod(T (&myArray)[N])
{
//N is number of elements, myArray is the array
std::cout<<"array elements number = "<<N<<endl;
//put your code
string temp;
temp.resize(N+1);//this is for performance not to copy it each time you use += operator
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
//call it like this
char arr[] = "hello world";
MyMethod(arr);

How to get the size of the used space in an array? (NOT sizeof); c++

#include<iostream>
using namespace std;
int main()
{
char arr[200];
while(1) {
cin >> arr;
int i = sizeof(arr);
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
For the input of 34,
This code outputs :The arr input is 34 and the size of the array is 200
while I want it to get the size of the used space of the array . So for The last input i want it to output :The arr input is 34 and the size of the array is 2
Can someone tell me how?
Maybe you want strlen(arr) here. It must be null terminated, otherwise the cout << arr would not have worked.
You would need to #include <cstring>
There's no automatic way to do what you want in the general case - you'll need to keep track somehow, either with your own counter, or by seeding the array with an 'invalid' value (that you define) and search for to find the end of the used elements (that's what the '\0' terminator character in a C-style string is).
In the example code you posted, the array should receive a null terminated C-style string, you can use that knowledge to count the number of valid elements.
If you're using C++ or some other library that has some more advanced data structures, you may be able to use one that keeps track of this kind of thing for you (like std::vector<>).
the size of the used space of the array
There is no such thing. If you have an array of 200 chars, then you have 200 chars. Arrays have no concept of "used" and "unused" space. It only works with C-strings because of the convention that those are terminated by a 0 character. But then again, the array itself cannot know if it is holding a C-string.
in a less involved manner, you can just count through each character till you hit a null with just a while loop. It will do the exact same thing strlen() does. Also, in practice, you should do type checking with cin, but i'll assume this was just a test.
#include <iostream>
using namespace std;
int main()
{
char arr[200];
int i;
while(1) {
cin >> arr;
i=0;
while (arr[i] != '\0' && i<sizeof(arr))
i++;
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
Just for completeness, here is a much more C++ like solution that is using std::string instead of a raw char array.
#include <iostream>
#include <string>
int
main()
{
while (std::cin.good()) {
std::string s;
if (std::cin >> s) {
std::cout
<< "The input is " << s
<< " and the size is " << s.length()
<< std::endl;
}
}
return 0;
}
It doesn't use an array, but it is the preferable solution for this kind of problem. In general, you should try to replace raw arrays with std::string and std::vector as appropriate, raw pointers with shared_ptr (scoped_ptr, or shared_array, whatever is most appropriate), and snprintf with std::stringstream. This is the first step to simply writing better C++. You will thank yourself in the future. I wish that I had followed this advice a few years ago.
Try it
template < typename T, unsigned N >
unsigned sizeOfArray( T const (&array)[ N ] )
{
return N;
}