如何以漂亮的格式放置不同的 C 字符串
how to put different C strings in a pretty format?
我正在编写一个简单的程序,用于构建当前目录的目录索引。
每个文件有两个 char* 对象用于文件名和上次修改时间,还有一个整数用于文件大小。
我想把所有这些放在一个大string
或char*
.
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
char* file_info(char*);
int main(void)
{
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
file_info(dir->d_name);
}
closedir(d);
}
return(0);
}
char* file_info(char* file) {
if(file[0] != '.') {
struct stat sb;
if (stat(file, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* lm = ctime(&sb.st_mtime);
*lm = ' ';
stringstream ss;
ss << file << " " << lm << " " << sb.st_size;
cout << ss.str() << endl;
}
return lm;
}
我希望返回的char*
是具有以下格式内容的对象:
homework-1.pdf 12-Sep-2013 10:57 123K
homework-2.pdf 03-Oct-2013 13:58 189K
hw1_soln.pdf 24-Sep-2013 10:36 178K
hw2_soln.pdf 14-Oct-2013 09:37 655K
间距是这里的主要问题。如何轻松更正?到目前为止,我的尝试是
const char* file_info(char* file) {
if(file[0] != '.') {
struct stat sb;
if (stat(file, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* lm = ctime(&sb.st_mtime);
string lastmod(lm);
lastmod.at(lastmod.size()-1) = ' ';
stringstream ss;
string spacing = " ";
ss << file << spacing.substr(0, spacing.size() - sizeof(file)) << lastmod << spacing.substr(0, spacing.size() - lastmod.size()) << sb.st_size;
cout << ss.str() << endl;
return ss.str().c_str();
}
else {
return NULL;
}
}
但它没有用,我用琴弦工作得很差。
这是问题所在:
// ...
stringstream ss;
// ...
return ss.str().c_str(); // woops! ss goes out of scope and string will be destroyed!
这可以通过使函数返回std::string
而不是char const*
并执行以下操作来轻松解决:
return ss.str();
没有理由在这里返回char const*
。它使一切复杂化,需要手动内存管理,在某些时候会异常不安全,使调用函数的人感到困惑,并使代码完全无法维护。
要回答您的 iostream 格式问题,您需要 std::setw
std::cout << "'" << std::setw(16) << "Hello" << "'" << std::endl;
http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node83.html
有两个不同的问题。首先,您显然无法从堆栈分配的函数中返回const char *
。因此,您必须将其分配给堆。这就是问题所在。这是所有权问题。你必须在哪里delete
这个字符串?通过使用std::string
可以轻松解决。
第二个问题是你的问题。如何使其很好地对齐。使用您的方法,您不能打印比预分配字符串更长的文件名。有 si 简单的解决方案。在标头iomanip
中定义了函数
/*unspecified*/ std::setw( int n );
上面写着"嘿,接下来你要打印的必须n
个字符长"。这就是你想要的。当您要打印的东西更长时,n
它将被全部打印出来。没有裁剪或类似的东西。
必须使用以 null 结尾的 C 字符串,而不是使用 sprintf 而不是 std::stringstream。像这样混合 C 和 C++ 被认为是不好的做法(就像已经指出的那样:即您必须手动管理内存)。您的代码还存在一些其他问题:sizeof() 运算符不计算字符串的长度 - 而是计算必要的内存空间(以字节为单位)。返回对 ctime 内部缓冲区的引用也不安全:
该函数还访问和修改共享内部缓冲区, 这可能会导致对 ASCtime 或 ctime 的并发调用出现数据争用
而是使用按引用调用,不返回任何内容。喜欢这个:
void file_info(char* file, char* buffer) {
if(file[0] != '.') {
struct stat sb;
if (stat(file, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* lm = ctime(&sb.st_mtime);
*lm = ' ';
sprintf(buffer, "%10s%10s%d", file, lm, sb.st_size);
}
}
要解决格式化问题,您还可以使用 strlen()(但不是 sizeof())并根据 lm 和文件的长度使用空格。但是 sprintf 提供了一个固定长度的参数,其中包含 %"位数"。
另请参阅:打印参考
要打印的最小字符数。如果要打印的值 小于此数字,则结果填充空格。 即使结果更大,也不会截断该值。
但是在调用此函数之前,您需要为 char* 缓冲区分配内存,并且必须确保它对于 sprintf 字符串(!) 来说足够大。
即
char buffer[256];
file_info(file, buffer);
printf("%sn", buffer);
谢谢大家的回答。
但是,它们都没有像我预期的那样工作。(特别是,它不是用于输出,而是用于制作字符串对象。
我最终实现了我想要的,但这绝不是好的。
不过,我在下面附上我的程序。随意发表评论。
谢谢。
void file_info(char*, stringstream&);
int main(void)
{
DIR *d;
struct dirent *dir;
d = opendir(".");
stringstream ss;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
file_info(dir->d_name, ss);
}
closedir(d);
}
cout << ss.str() << endl;
return(0);
}
void file_info(char* file, stringstream& ss) {
if(file[0] != '.') {
struct stat sb;
if (stat(file, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* lm = ctime(&sb.st_mtime);
string lastmod(lm);
lastmod.at(lastmod.size()-1) = ' ';
string spacing = " ";
ss << file << spacing.substr(0, spacing.size() - strlen(file)) << lastmod << spacing.substr(0, spacing.size() - lastmod.size()) << sb.st_size << 'n';
}
return;
}
- 字符串::格式有什么用. 我也没有在互联网上得到它
- 如何检查字符串格式在读取C++文本文件时是否有效?
- 十进制到八进制递归C++.以标准::字符串格式输出
- 如何从字符串格式中提取 3 个整数"v%d.%d.%d"?
- 查找可变参数列表的字符串格式指定符
- 字符串格式替换为 snprintf 中字符中的值
- 使用堆栈将字符串格式的十进制转换为双精度
- 使用字符串格式限制十六进制数字的数量
- 视觉C++:字符串格式
- C++字符串格式实现错误
- 如何在Xcode中将长双精度转换为字符串格式?或如何解决错误"use of undeclared identifier 'to_string' "
- C++以字符串格式 YYYYMMDD 减去天数
- 如何在windows和linux中使用相同的宽字符串格式
- 如何将标准::字符串格式的 JSON 解码为 Boost 属性树
- C++格式的字符串格式
- 使用C++将任何形式的日期-时间字符串格式更改为美国日期-时间格式
- 使用C/C++设置字符串格式
- 如何创建以字符串格式使用给定变量文本的宏(或其他工具)
- 如何转换?toString() 的 C 字符串格式
- 用字符串格式运算符替换C++字符串