为什么视觉c ++和mingw的输出有这么大的差异 [英] Why so much difference in output of visual c++ and mingw

查看:112
本文介绍了为什么视觉c ++和mingw的输出有这么大的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对文件进行base64编码和解码并在输出屏幕上显示。

我的输入文件如下:



换句话说
MAC地址:XY-XX-XX-XX-XX-XXX可以是任何十六进制的。以二进制格式写的十六进制Y是Y:kmnp,其中p是最低有效位;

p = 0 - >单播;
p = 1 - >组播;
n = 0 - >全球指定的MAC;
n = 1 - >在当地管理;
因此,实际上MAC可以更改为p = 0和n = 1的任意组合;

Y可以是2,6,A或E.

因此Windows 7中针对无线适配器的可能MAC地址:





我的代码是:

  #include   <   stdio.h  >  
#include < string.h >
#include < 字符串 >
#include < cmath >
#include < cassert >
#include < limits >
#include < stdexcept >
#include < < span class =code-leadattribute> cctype >
#include < iostream >

使用 std :: cout;
使用 std :: endl;

static const int CHARS = 57 ;

static const char b64_table [ 65 ] = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + / ;

static const char reverse_table [ 128 ] = {
64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64
64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64
64 64 64 64 64 64 64 64 64 64 64 62 64 64 64 63
52 53 54 55 56 57 58 59 60 61 64 64 64 64 64 64
64 0 1 2 3 4 5 ,< span class =code-digit> 6
7 8 9 10 11 12 , 13 14
15 16 17 ,< span class =code-digit> 18 , 19 20 21 22 23 24 25 64 64 64 64 64
64 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50 51 64 64 64 64 64
};

std :: string base64_encode( const :: std :: string& bindata)
{
使用 :: std :: string;
使用 :: std :: numeric_limits;

if (bindata.size()>(numeric_limits< string :: size_type> :: max()/ 4u)* 3u) {
throw :: std :: length_error( 将过大的字符串转换为base64。);
}

const :: std :: size_t binlen = bindata.size();
// 使用=符号以便正确填充结尾。
string retval ((((binlen + 2 )/ 3 )* 4 ),' =');
:: std :: size_t outpos = 0 ;
int bits_collected = 0 ;
unsigned int accumulator = 0 ;
const string :: const_iterator binend = bindata.end();

for (string :: const_iterator i = bindata.begin(); i!= binend; ++ i){
accumulator =(累加器<< 8 )| (* i& 0xffu);
bits_collected + = 8 ;
while (bits_collected> = 6 ){
bits_collected - = 6 ;
retval [outpos ++] = b64_table [(accumulator>> bits_collected)& 0x3fu];
}
}
如果(bits_collected> 0 ){ // 缺少任何尾随位。
assert(bits_collected< 6 );
accumulator<< = 6 - bits_collected;
retval [outpos ++] = b64_table [accumulator& 0x3fu];
}
断言(outpos> =(retval.size() - 2 ));
断言(outpos< = retval.size());
return retval;
}

std :: string base64_decode( const :: std :: string& ascdata)
{
使用 :: std :: string;
string retval;
const string :: const_iterator last = ascdata.end();
int bits_collected = 0 ;
unsigned int accumulator = 0 ;

for (string :: const_iterator i = ascdata.begin(); i!= last; ++ i){
const int c = * i;
if (:: std :: isspace(c)|| c == ' < span class =code-string> ='
){
// 跳过空格和填充。在接受的内容中保持自由。
继续;
}
如果((c> 127 )||(c< ; 0 )||(reverse_table [c]> 63 )){
throw :: std :: invalid_argument( 这包含不合法的字符在base64编码的字符串中。);
}
accumulator =(累加器<< 6 )| reverse_table [C];
bits_collected + = 6 ;
if (bits_collected> = 8 ){
bits_collected - = 8 ;
retval + =( char )((累加器>> bits_collected)& 0xffu);
}
}
return retval;
}
struct upload_status
{
int lines_read ;
};

char (* read_file())[CHARS]
{
FILE * hFile = NULL;
char (* fileBuf)[CHARS] = NULL;
std :: string fileName( Hello.txt);
size_t fileSize,len( 0 );

// 打开文件
hFile = fopen(fileName .c_str(), rb);
if (hFile == NULL)
throw 文件不存在。;

// 获取文件大小
fseek(hFile,< span class =code-digit> 0 ,SEEK_END);
fileSize = ftell(hFile);
fseek(hFile, 0 ,SEEK_SET);

// 检查文件大小
if (fileSize> 1 * 1024
{}

int no_of_rows = fileSize / 54 + 1 ;
fileBuf = new char [no_of_rows + 1 ] [煤焦]; // 我们在条件语句中使用的特殊字符的额外行,这里

for (len = 0 ; len< no_of_rows; ++ len)
fread(fileBuf [len], sizeof char ), 54 ,HFILE);

strcpy(fileBuf [len], );
return fileBuf;
}

int main()
{
char *数据;
char (* FEdata)[CHARS] = NULL;
int len( 1 );
struct upload_status upload_ctx;
upload_ctx.lines_read = 0 ;
std :: string str,Estr( );
FEdata = read_file();

while (len)
{
data = FEdata [upload_ctx.lines_read];
if (strcmp(data, ))
{
size_t len = strlen(data);
str = std :: string(data);
Estr + = base64_encode(str);
cout<< base64_encode(str);
upload_ctx.lines_read ++;
继续;
}
len = 0 ;
}
cout<< \ n \ nn \ n \\ n << BASE64_DECODE(雌甾);
return 0 ;
}



此代码在mingw编译器中运行良好,但在visual c ++中它显示了超长的编码和解码(我的意思是它正常工作。)

有什么建议??

解决方案

有什么问题? base64编码的字符串的长度?原始数据和编码数据之间没有严格的一对一对应关系,因为base64格式有点自由;它可以以任意方式格式化,这可能会产生一些额外的长度。原始,编码和解码数据的往返行为具有相同的结果;这一切都很重要。您还可以通过一个程序对数据进行编码,使用另一个程序进行解码并比较结果。







感谢您显示您的代码和数据。



我可以看到,只有第一个,更短的base64文本是正确的,我通过测试发现。我只能提出一个建议。您正在使用一些通用整数类型行 int 。对于所有环境,它们没有固定大小。其中一个编译器可以使用一个大小,默认假设只使用这个大小,另一个编译器使用不同的大小。现在,有时整数数据会溢出整数对象,例如,如果向最大值的无符号整数添加一个位,它就会翻转。通常这是以未经检查的方式完成的。



换句话说,代码不正确,但它随便为其中一个编译器生成正确的结果。因此,做以下实验:找出正确编译器的所有通用整数类型的大小(它们都同样不正确,只使用产生工作算法的那个)。您始终可以使用 sizeof 运算符,看看它们是什么。在了解所有类型的尺寸后,将其替换为固定尺寸的尺寸。确保代码仍然有效。当你实现这一点时,尝试用另一个编译器编译它。







例如,您可以使用boost库中提供的固定大小的整数类型定义: http ://www.boost.org/doc/libs/1_38_0/libs/integer/index.html [ ^ ]。



-SA


经过长时间的观察,我发现visual c ++在文件指针方面表现得非常奇怪。



看看我从执行以下代码得到了什么:



  #include   <   stdio.h  >  
#inclu de < iostream >

使用 std :: cout;
使用 std :: endl;

int main()
{
FILE * file;
size_t fileSize;
char * str;
file = fopen( Hello.txt rb);

str = new char [ 54 ];
fread(str, sizeof char ), 53 ,文件);
cout<< str;
return 0 ;
}
< / iostream>< /stdio.h>





在mingw输出是:

换句话说
MAC地址:ôXY-XX-XX-XX-XX-XXöôXö





但是在visual c ++中它是:

换句话说
MAC地址:ôXY-XX-XX- XX-XX-XXöôXö=²²²½½½½½½½■ε■ε■





Visual c ++打印直到找到NULL,它不是放读完后为NULL。这不是我们想要的。

所以每次我们从文件中读取时都要把'\0'放在最后。

所以更新for循环read_file()如下:

  int  no_of_rows = fileSize / 54 +  1 ; 
int read( 0 );
fileBuf = new char [no_of_rows + 1 ] [煤焦];

for (len = 0 ; len< no_of_rows; ++ len )
{
read = fread(fileBuf [len], sizeof char ), 54 ,hFile);
fileBuf [len] [read] = ' \0';
}



现在代码在visual c ++和mingw中的工作方式相同。 :)


I want to base64 encode and decode a file and show it on the output screen.
My input file is as follows:

In other words
MAC address: "XY-XX-XX-XX-XX-XX" "X" can be anything hexadecimal. The hexadecimal "Y", written in binary format, is Y: "kmnp", where "p" is the least significant bit;

        p=0 --> unicast; 
        p=1 --> multicast; 
        n=0 --> globally assigned MAC; 
        n=1 --> locally administered; 
So, actually MAC can be changed to any combination in which p=0 and n=1;

"Y" can be 2, 6, A or E.

So the possible MAC addresses in Windows 7 for wireless adapters:



My code is:

#include <stdio.h>
#include <string.h>
#include <string>
#include <cmath>
#include <cassert>
#include <limits>
#include <stdexcept>
#include <cctype>
#include <iostream>

using std::cout;
using std::endl;

static const int CHARS= 57;	

static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static const char reverse_table[128] = {
   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
   52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
   64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
   64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
};

std::string base64_encode(const ::std::string &bindata)
{
   using ::std::string;
   using ::std::numeric_limits;

   if (bindata.size() > (numeric_limits<string::size_type>::max() / 4u) * 3u) {
      throw ::std::length_error("Converting too large a string to base64.");
   }

   const ::std::size_t binlen = bindata.size();
   // Use = signs so the end is properly padded.
   string retval((((binlen + 2) / 3) * 4), '=');
   ::std::size_t outpos = 0;
   int bits_collected = 0;
   unsigned int accumulator = 0;
   const string::const_iterator binend = bindata.end();

   for (string::const_iterator i = bindata.begin(); i != binend; ++i) {
      accumulator = (accumulator << 8) | (*i & 0xffu);
      bits_collected += 8;
      while (bits_collected >= 6) {
         bits_collected -= 6;
         retval[outpos++] = b64_table[(accumulator >> bits_collected) & 0x3fu];
      }
   }
   if (bits_collected > 0) { // Any trailing bits that are missing.
      assert(bits_collected < 6);
      accumulator <<= 6 - bits_collected;
      retval[outpos++] = b64_table[accumulator & 0x3fu];
   }
   assert(outpos >= (retval.size() - 2));
   assert(outpos <= retval.size());
   return retval;
}

std::string base64_decode(const ::std::string &ascdata)
{
   using ::std::string;
   string retval;
   const string::const_iterator last = ascdata.end();
   int bits_collected = 0;
   unsigned int accumulator = 0;

   for (string::const_iterator i = ascdata.begin(); i != last; ++i) {
      const int c = *i;
      if (::std::isspace(c) || c == '=') {
         // Skip whitespace and padding. Be liberal in what you accept.
         continue;
      }
      if ((c > 127) || (c < 0) || (reverse_table[c] > 63)) {
         throw ::std::invalid_argument("This contains characters not legal in a base64 encoded string.");
      }
      accumulator = (accumulator << 6) | reverse_table[c];
      bits_collected += 6;
      if (bits_collected >= 8) {
         bits_collected -= 8;
         retval += (char)((accumulator >> bits_collected) & 0xffu);
      }
   }
   return retval;
}
struct upload_status 
{
  int lines_read;
};

char (*read_file())[CHARS]
{
	FILE* hFile=NULL;
	char (*fileBuf)[CHARS] =NULL;
	std::string fileName("Hello.txt");
	size_t fileSize,len(0);

	//opening the file
	hFile = fopen(fileName.c_str(),"rb");
	if (hFile == NULL)
		throw "File Does not exist.";

	//get file size
	fseek(hFile,0,SEEK_END);
	fileSize = ftell(hFile);
	fseek(hFile,0,SEEK_SET);

	//Checking file size
	if(fileSize > 1*1024)
	{}

	int no_of_rows = fileSize/54 + 1;
	fileBuf = new char[no_of_rows + 1][CHARS];	//Extra row for our special character to be used in conditional statements,here ""

	for (len=0 ; len < no_of_rows; ++len)
		fread(fileBuf[len],sizeof(char),54,hFile);

	strcpy(fileBuf[len],"");
	return fileBuf;
}

int main()
{
	char *data;
	char (*FEdata)[CHARS] = NULL;
	int len(1);
	struct upload_status upload_ctx;
	upload_ctx.lines_read = 0;
	std::string str,Estr("");
	FEdata = read_file();

	while (len)
	{
	  data = FEdata[upload_ctx.lines_read];
	  if(strcmp(data,"")) 
	  {
		size_t len = strlen(data);
		str = std::string(data);
		Estr += base64_encode(str);
		cout<<base64_encode(str);
		upload_ctx.lines_read++;
		continue;
	  }
	  len = 0;
	}
	cout<<"\n\n\n\n"<<base64_decode(Estr);
	return 0;
}


This code is working well in mingw compiler, but in visual c++ its showing extra long encoding and decoding(I mean it's working as it should.)
Any suggestion ??

解决方案

What's the problem? The length of base64-encoded string? There is no strict one-to-one correspondence between original and encoded data, as the base64 format is somewhat free; it can be formatted in arbitrary manner, which may create some extra length. The round trip of original, encoded and then decoded data does the same result; this is all that matters. You can also encode data by one program, decode with another one and compare the results.

[EDIT #1]

Thank you for showing your code and data.

As I can see, only first, shorter base64 text is correct, which I found by testing it. I have only one suggestion I can thing of. You are using some generic integer types line int. They don't have one fixed size for all environment. One of the compilers could use one size, silently assuming that only this size will be used, another compiler used different size. Now, sometimes integer data overflows integer objects, say, if you add a bit to an unsigned integer of maximum value, it rolls over. And usually this is done in unchecked way.

In other words, the code is incorrect, but it "casually" produce correct result for one of the compiler. So, do the following experiment: find out the sizes of all of the generic integer types for "correct" compilers (they all are equally "incorrect", just use the one which produced the working algorithm). You can always use sizeof operator and see what are they. After you learn the sizes of all those types, replace them with the sizes of fixed size. Make sure the code still works. And when you achieve that, try to compile it by another compiler.

[EDIT #2]

You can use, for example, fixed-size integer type definitions provided in boost library: http://www.boost.org/doc/libs/1_38_0/libs/integer/index.html[^].

—SA


After a very long observation I found that visual c++ behaves in a very strange why when it comes to file pointers.

See what i get from executing the following code:

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;

int main()
{
	FILE* file;
	size_t fileSize;
	char* str;
	file = fopen("Hello.txt","rb");

	str = new char[54];
	fread(str,sizeof(char),53,file);
	cout<<str;
	return 0;
}
</iostream></stdio.h>



In mingw the output is :

In other words
MAC address: ôXY-XX-XX-XX-XX-XXö ôXö



But in visual c++ it is:

In other words
MAC address: ôXY-XX-XX-XX-XX-XXö ôXö ═²²²²½½½½½½½½ε■ε■ε■



Visual c++ is printing until it finds a NULL, it is not putting a NULL after reading. Which is not what we want.
So we have to put '\0' at the end every time we read from the file.
So update the for loop in the read_file() as follows:

int no_of_rows = fileSize/54 + 1;
int read(0);
fileBuf = new char[no_of_rows + 1][CHARS];

for (len=0 ; len < no_of_rows; ++len)
{
    read = fread(fileBuf[len],sizeof(char),54,hFile);
    fileBuf[len][read] ='\0';
}


Now the code works the same in both visual c++ and mingw. :)


这篇关于为什么视觉c ++和mingw的输出有这么大的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆