C++ 堆栈程序 指针问题的 Wsing 数组 新字符[len],其中 len 为 2 创建 16 个字符
C++ Stack Program Wsing array of Pointer Issue new char[len] where len is 2 creates a char of 16?
好的,所以我正在为类编写一个程序,我对c ++的方式不是很熟悉。我已经研究了字符数组,但无法找出问题所在。似乎在分配空间时,空终止符未在所需位置分配。
我的问题是这个。我正在分配一个数组,如下所示:
char* St ="";
if(P.GetSize() > 0)
{
int StLen = P.GetSize() + 1;
St= new char[StLen];
int i;
for( i = 0;!P.isEmpty() && i < (int)strlen(St); i++)//StLen
{
*(St+i)= P.getTop();
P.Pop();
}
*(St+i) = 0;
std::reverse( St, &St[ strlen( St ) ] ); //flip string to display bottom to top
}
如果 P.GetSize(( 为 1 并且我为空终止符添加一个,则行 (int(strlen(St( 仍然返回 16 作为长度,这是我读入的数组的原始长度。我在下面发布了我的工作计划,供其他有相同问题的人参考
以下是我的工作解决方案头文件:
//Created By : Timothy Newport
//Created on : 4/26/2012
//===========================================
// NewportStack.h
//============================================
#pragma once
#include <iostream>
#include <iomanip>
#include <fstream>
#include <crtdbg.h>
#include <stack>
#include <string>
using namespace std;
const int MAX_POSTFIX = 30;
void infixToPostfix(const char *infix, char* postfix,ostream& os);
void WriteHeader(ostream& os);
void WriteResults(ostream& os,const char *postfix);
template<class T>
struct Node
{
T data;
Node<T> *prev;
};
template<class T>
class NewportStack
{
private:
Node<T> *top;
int size;
public:
NewportStack();
NewportStack(const NewportStack <T> & displayStack);
~NewportStack();
void Push(T ch);
void Pop();
T getTop() const;
bool isEmpty() const;
const int GetSize() const;
int SetSize(const int prvSize);
bool checkPresidence(T data,char infix);
void printStack() const;
virtual ostream& Output (ostream& os, const NewportStack & S,
const char infix,const char *postfix
,const int size) const;
};
//------------
//Constructor
//------------
template<class T>
NewportStack<T>::NewportStack()
{
top = NULL;
size = 0;
}
template<class T>
void NewportStack<T>::printStack() const
{
Node<T>* w;
w = top;
while( w != NULL )
{
cout << w->data;
w = w->prev;
}
}
//------------
//Copy Constructor
//------------
template<class T>
NewportStack<T>::NewportStack(const NewportStack<T> &Orig)
{
if (Orig.top == NULL) // check whether original is empty
{
top = NULL;
}
else
{
Node<T>* newPrev=new Node<T> ;
Node<T>* cur = Orig.top;
newPrev->data = cur->data;
top = newPrev;
// Now, loop through the rest of the stack
cur = cur->prev;
while(cur != NULL )
{
newPrev->prev = new Node<T>;
newPrev = newPrev->prev;
newPrev->data = cur->data;
cur = cur->prev;
} // end for
newPrev->prev = 0;
cur = 0;
} // end else
size = Orig.size;
} // end copy constructortor
//------------
//DeConstructor
//------------
template<class T>
NewportStack<T>::~NewportStack()
{
Node <T>* w = top;
while(top!=NULL)
{
delete w;
top=top->prev;
}
size =0;
}
//------------
//getsize
//------------
template<class T>
const int NewportStack<T>::GetSize() const
{
return size;
}
//------------
//SetSize
//------------
template<class T>
int NewportStack<T>::SetSize(const int prvSize)
{
return size = prvSize;
}
//------------
//Push
//------------
template<class T>
void NewportStack<T>::Push(T d)
{
Node <T>* w= new (std::nothrow) Node<T>;
if ( !w )
{
cerr << "Error out of memory in Pushn";
exit (1);
}
w->data =d;
if( top == NULL )
{
w->prev = NULL;
}
else
{
w->prev = top;
}
top = w;
w = NULL;
size++;
}
//------------
//Pop
//------------
template<class T>
void NewportStack<T>::Pop()
{
if( top == NULL )
return;
Node<T>* w = top;
top = top->prev;
delete w;
w = NULL;
size--;
}
//------------
//getTop
//------------
template<class T>
T NewportStack<T>::getTop() const
{
if (isEmpty ())
exit(0);
return top->data;
}
//------------
//isEmpty
//------------
template<class T>
bool NewportStack<T>::isEmpty() const
{
if(top == NULL)
{
return true;
}
return false;
}
//------------
//checkPresidence
//------------
template<class T>
bool NewportStack<T>::checkPresidence(T data,char infix)
{
switch(infix)
{
case '+': case '-':
switch(data)
{
case '+': case '-': case '*': case '/': case '%':
return true;
default: return false;
}
case '*': case '/': case '%':
switch(data)
{
case '*': case '/': case '%':
return true;
default: return false;
}
default: return false;
}
}
//------------
//OutPut
//------------
template<class T>
ostream& NewportStack<T>::Output(ostream& os, const NewportStack<T>& S,
const char infix,const char *postfix
,const int size) const
{
NewportStack<T> P ( S );//***INVOKED COPY CONSTRUCTOR*****
char* St = new char[21];
int i;
if(P.GetSize() > 0)
{
int StLen = P.GetSize();
for( i = 0;!P.isEmpty();i++)
{
*(St+i)= P.getTop();
P.Pop();
}
*(St+i) = 0;
std::reverse( St, &St[ strlen( St ) ] ); //flip string to display bottom to top
}
else
*(St+0) = 0;
os <<left<<setw(20) << infix ;
for(i = 0;i < (int)strlen(St);i++)
{
os << St[i];
}
os << right<< setw(21-i);
for(i = 0;i <size;i++)
{
os << postfix[i];
}
os << endl;
if(St != NULL)
{
delete[] St;
}
return os;
}
CPP文件在这里:
//Created By : Timothy Newport
//Created on : 4/26/2012
//===========================================
// NewportStackTester.cpp
//============================================
#include "NewportStack.h"
//------------
//Main
//------------
int main()
{
//////////////////////////////////////////
/// Tester Part Two Test The class ///
//////////////////////////////////////////
char arr[] = "a+b-c*d/e+(f/g/h-a-b)/(x-y)*(p-r)+d";
//char arr[] = "a+b-c*d/e+(f/g)";
int len = (int) strlen(arr);
char *postfix = new char[len+1];
ofstream outputFile;
outputFile.open("PostFix.txt");
outputFile << "Infix is : " << arr<<endl<<endl;
WriteHeader(outputFile);
_strupr( arr); ///**** convert the string to uppercase ****
infixToPostfix(arr,postfix,outputFile);
outputFile.close();
system("notepad.exe PostFix.txt");
return 0;
}
//------------
//infixToPostfix
//------------
void infixToPostfix(const char *infix, char* postfix, ostream & os)
{
NewportStack <char> P;
int len=strlen(infix);
len += 1;
// cout << "infix in infixToPostfix: " << infix << endl;
int pi = 0;
int i=0;
char ch;
while( i < len && *(infix+i) !=' ')
{
ch = *(infix+i);
if(ch >='A' && ch <='Z' )
{
postfix[pi++]= ch;
}
else if(ch =='+' ||ch =='-'||ch =='*'||ch =='/'||ch =='%')
{
while(!P.isEmpty() && P.getTop() != '('
&& P.checkPresidence(P.getTop(), ch ) )
{
postfix[pi++]= P.getTop();
postfix[pi] = 0;
P.Pop();
}
P.Push(ch);
}
else if(infix[i] == '(')
{
P.Push(infix[i]);
}
else// if(infix[i]==')')
{
while(!P.isEmpty() && P.getTop() != '(')
{
postfix[pi++] = P.getTop();
P.Pop();
}
P.Pop(); //****remove the '(' from the stack top.
}
P.Output(os, P, ch, postfix, pi); // display after each read
i++;
}
// end of infix empty stack
while(!P.isEmpty() )
{
postfix[pi++]= P.getTop();
P.Pop();
}
postfix[pi] = 0; //add null terminator at the end of the string.
//cout << "postfix 104: " << postfix << endl;
P.Output(os,P,*infix,postfix,pi);// display final line
WriteResults(os,postfix);
}
//------------
//WriteHeader
//------------
void WriteHeader(ostream& os)
{
os <<left<< setw(20)<< "Input Characters" << setw(20)<< "Stack Item" << setw(20)
<< "PostFix" <<endl <<setw(20)<< "----------------"<< setw(20)
<< "----------" << setw(20)<< "-------" <<endl;
}
//------------
//WriteResults
//------------
void WriteResults(ostream& os,const char *postfix)
{
os << endl<< "The Final postfix is: " << postfix <<endl;
}
你们帮了我这么多!我只是一直在搞砸它,直到我发现主要问题。
new char[StLen];
不初始化内存。您应该使用 std::string
,而不是像这样手动处理字符数组。
如果强制手动使用字符数组,则可以编写自己的自动内存管理包装器来处理释放,并且可以通过在第一个索引处写入' '
字符将内存初始化为以 null 结尾的字符串。
我首先想到的是,你不能在 char 数组上使用 strlen((,除非你绝对确定它是一个以零结尾的字符串。在你的循环条件下,你应该检查(i <(StLen - 1((而不是调用 strlen((。strlen(( 对数组长度一无所知;它只是在命中"\0"值的字符之前报告字节数。在您的平台上检查"man strlen",或者,如果不可用,则在网络上搜索"man strlen"。我实际上有点惊讶这并没有由于访问违规而直接崩溃。
[编辑:听R. Martinho Fernandes。您正在使用 C 约定和 C 标准库处理字符串。在C++有更好、更安全的方法可以做到这一点,除非你的教练告诉你不这样做。
[编辑]:如果出于某种原因你知道你会将一个未初始化的字符数组传递给strlen((,那么将第一个字节设置为'\0',就像另一个海报建议的那样,将使strlen((满意。但是再看看你的代码,我真的怀疑strlen((是你想在这里做的。我认为这会给你一个逻辑错误。请参阅我上面的循环条件建议。
至于初始化 C 样式零终止字符串的正确方法,您希望使用值为 '\0' 的 memset((,如
memset(St, ' ', StLen);
我相信原型在字符串中。 这将减少以后弄乱字符串完整性的方式数量,至少在您第一次写入它时是这样。始终初始化内存是一种很好的常规做法,但对于以零结尾的字符串尤其重要。
如果你打算使用零终止的字符串做更多的工作,一个好的经验法则是"str"函数通常是不安全的,而"strn"函数在可用和可行时是首选的。当然,"strn"函数通常更易于使用,因为您必须跟踪缓冲区大小。请参阅 strcpy(( 和 strncpy(( 或 strcat(( 和 strncat(( 的手动条目以了解差异。但同样,我认为 strlen(( 甚至不是你想要的。
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 指向指向字符数组的指针数组的指针
- 如何用转义符替换字符串中的所有特殊字符
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 比较字符数组
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 为什么字符串(常量字符* s,size_t pos,size_t len = npos)有效?
- C++ 堆栈程序 指针问题的 Wsing 数组 新字符[len],其中 len 为 2 创建 16 个字符