- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为一个学校项目工作,但遇到了一些麻烦。该项目的要旨是编写一个程序,该程序读取文本文件并格式化该文件,以使其适合特定的宽度。要格式化该文件,用户需要指定输入文件,输出行的长度以及输出文本的理由。一个例子是这样的:
$ ./format test.dat 15 rightThe quick brown fox jumps over the lazy old dog.$ ./format test.dat 15 leftThe quick brownfox jumps overthe lazy olddog.$ ./format test.dat 15 centerThe quick brownfox jumps over the lazy old dog.
Anyway, I am basically stuck on how to go about outputting the file based on this. Attached below is my code for reading in the file, and what little I have done on outputting the file. I am mainly looking for tips or suggestions on how to go about doing it. I know I need to use printf with a width and such, but I am confused on how to move to the next line.
char **inputFile(FILE *fp, int size) {
int i = 0;
char *token;
char **str;
str = malloc(sizeof(char *) * size);
token = readToken(fp);
while(!feof(fp)) {
if(i+1 == size) {
realloc(str, size * 2);
}
str[i] = token;
token = readToken(fp);
i++;
}
return str;
}
void toPrint(char **string, int width, int indent) {
int i;
int curLineLength;
if(indent == 0) {
for(i = 0; I < strlen(string); i++
char *token = string[i];
if(curLineLength + strlen(*string) > width) {
if(curLineLength > 0) {
printf("\n");
curLineLength = 0;
}
}
printf("%s ", token);
curLineLength += strlen(*string);
}
/*
if(indent == 1) {
}
if(indent == 2) {
}
*/
}
最佳答案
从注释开始,证明行对齐的任务比构造输出函数更多的是逻辑挑战,而不是困难的挑战。你越来越近了。有很多方法可以做到,您可能需要添加错误检查以确保width
不小于最长的行。
这是您可以借鉴的简单示例。确保您了解每行的编写方式,并密切注意可变长度数组的定义(您将需要编译为c99-或如果使用gcc,则依赖gcc扩展名(默认))。如果您有任何问题,请告诉我:
/* format 'n' lines of output of 't' justified as specified in 'just'
(left 'l', right 'r' or centered 'c') within a width 'w'.
NOTE: 'w' must be larger than the longest line in 't'.
*/
void formatted (char **t, char just, size_t w, size_t n)
{
if (!t || !*t) return;
size_t i = 0;
size_t lmax = 0;
size_t len[n];
/* calculate the length of each line, set lmax */
for (i = 0; i < n; i++) {
len[i] = strlen (t[i]);
if (len[i] > lmax) lmax = len[i];
}
/* handle w < lmax reformat or error here */
if (w < lmax) {
fprintf (stderr, "%s() error: invalid width < lmax (%zu).\n",
__func__, lmax);
return;
}
/* left justified output */
if (just == 'l') {
for (i = 0; i < n; i++) {
printf ("%s\n", t[i]);
}
return;
}
/* center or right justified output */
for (i = 0; i < n; i++) {
int spaces = w - len[i];
if (just == 'c')
printf ("%*s%s\n", spaces/2, " ", t[i]);
else if (just == 'r')
printf ("%*s%s\n", spaces, " ", t[i]);
}
}
__func__
更改为函数名称。
void formatted (char **t, char just, size_t w, size_t n)
char **t
,您的“字符串”,嗯……实际上是您键入
char*
的数组或指针。当您将指针数组传递给函数时,这可能就是您的困惑所在,您只有两种方法可以遍历数组,在每一行文本中进行打印:(1)传递指向该指针的有效指针数到包含文本的字符串,或(2)在数组内提供一个由指向最后一个指向文本有效行的指针所指向的指针。 (通常只是
NULL
)前哨充当数组中的指针,告诉您(“假人,停止尝试打印行-您已经打印了最后一行...”)
realloc
数组包含更多空间。这意味着您在未填充数组的末尾将始终至少有1个指针。如果要在一开始就初始化数组以包含
NULL
指针(通过使用
calloc
而不是
malloc
进行分配)-您将自动提供一个前哨,或者,您始终可以将下一个指针显式设置为
Pointer The pointers in the array of pointers to char*, char **t;
Address point to the first character in each associated string.
+-----------+
| 0x192a460 | --> The quick brown
+-----------+
| 0x192a480 | --> fox jumps over
+-----------+
| 0x192a4a0 | --> a lazy
+-----------+
| 0x192a4c0 | --> dog.
+-----------+
| NULL |
+-----------+
| NULL |
+-----------+
...
NULL
,我的
string
是
t
而不是字符串本身。您的
array of pointers to type char*
是上方指针的左列。
string
是每个真实字符串的起始地址的数组,而您的
string
将是实际字符串本身的起始-在该地址。
string[i]
的范围为
i
(总计
0-3
),其中
4
,
string[0] = "The quick brown"
等。要获得帮助,请将您的
string[1] = "fox jumps over"
代码中的名称更改为
string
或
array
以提供帮助保持直率。
for (i = 0; i < n; i++)
printf ("%s\n", t[i]);
while (t[i]))
printf ("%s\n", t[i++]);
str_array
即可)。您需要做的就是打印每个字符串。由于我们将字符串
width
的数量传递给函数,因此我们可以简单地使用
'n'
循环(方法1)来打印每个字符串。 (长度是在打印之前计算出来的,以确保每个字符串都适合
for
,因为我们稍后将使用它,因此我们将每个长度存储在可变长度数组
width
中,因此我们不必对< cc>稍后)
len
和
strlen
合理的情况。除了“ n”之外,您还需要知道用户想要的理由。您可以传递要将该信息传递给函数的任何类型标志。
center
(
right
)只是最有效的,并且在读取为程序输入时不需要转换为数字。从本质上讲,这就是为什么我选择将
char
作为
1-byte
而不是
just
(
char
+输入转换)(或
int
(
4-bytes
)等)传递的原因。
short
个字符的输出宽度。您的第一个字符串是
2-bytes
(可打印的)字符长(由于
20
,它实际上在内存中是
15
字符)字符末)。让我们直观地看到我们的可打印字符字符串在20个字符的缓冲区中的样子(您将使用该字符将字符串的右对齐副本保存在内存中,而不是进行打印)
|<------- 20 character width -------->|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | |T|h|e| |q|u|i|c|k| |b|r|o|w|n|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|<-- 15 character length -->|
spaces = width - length;
16
格式字符串中的
null-terminating
指令。在此特别有用的功能是可以在
minimum field width
参数列表中将字段宽度指令指定为变量。构造格式字符串和参数列表以实现我们的目标,我们有:
printf ("%*s%s\n", spaces, " ", t[i]);
printf
打印最小字段宽度
printf
(本质上会打印
spaces
空格-名称选择不佳),然后是指针数组
" "
中的实际字符串。
spaces
移位很多,而不能将整个
t[i]
的空格都切掉,最终它将移到我们想要的位置。 (我能听到您的头在打磨齿轮,还能闻到烟雾的味道-“但是,等等...
width - length
是一个奇数,我们正在使用整数!”-没关系,整数除法会好好处理的,如果我们将2而不是2.5移位,那就很好了,您将不能打印1/2个字符...因此,将它们放在一起以处理居中或右对齐的文本,您所需的全部是:
for (i = 0; i < n; i++) {
int spaces = w - len[i];
if (just == 'c')
printf ("%*s%s\n", spaces/2, " ", t[i]);
else if (just == 'r')
printf ("%*s%s\n", spaces, " ", t[i]);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 256
#define MAXL 64
char **inputfile (char ***t, FILE *fp, size_t *sz);
void formatted (char **t, char just, size_t w, size_t n);
void *xcalloc (size_t n, size_t s);
void freecdp (char **p, size_t n);
unsigned chr2lower (unsigned c);
int main (int argc, char **argv) {
if (argc < 4) { /* validate required arguments on command line */
fprintf (stderr, "error: insufficient input. "
"usage: %s just width [filename (stdin)]\n",
argv[0]);
return 1;
}
char **text = NULL; /* initialize all variables for main */
size_t lines = 0;
char j = 0; /* the following are ternary operators */
char just = argc > 1 ? *argv[1] : 'l'; /* sets defaults if no input */
size_t width = argc > 2 ? (size_t)strtol (argv[2], NULL, 10) : 0;
FILE *fp = argc > 3 ? fopen (argv[3], "r") : stdin;
/* read input from file */
if (!(inputfile (&text, fp, &lines))) { /* check if return is NULL */
fprintf (stderr, "error: file read failed '%s'.\n",
argc > 3 ? argv[3] : "stdin");
return 1;
}
j = chr2lower (just); /* force user input to lower-case */
if (j != 'l' && j != 'r' && j != 'c')
fprintf (stderr, "error: invalid justification '%c' "
"(defaulting to 'left').\n", just);
/* print output in requested justification */
formatted (text, j, width, lines);
/* free all memory allocated in program */
freecdp (text, lines);
return 0;
}
char **inputfile (char ***t, FILE *fp, size_t *sz)
{
if (!t || !sz) { /* validate parameters are not NULL */
fprintf (stderr, "%s() error: invalid parameters.\n", __func__);
return NULL;
}
if (!fp) { /* check that file pointer is valid */
fprintf (stderr, "%s() error: file open failed.\n", __func__);
return NULL;
}
size_t idx = 0; /* declare/initialize function variables */
size_t maxl = MAXL;
char ln[MAXC] = {0};
/* allocate MAXL number of pointers */
*t = xcalloc (MAXL, sizeof **t);
while (fgets (ln, MAXC, fp)) { /* read each line in file */
size_t len = strlen (ln); /* calculate length */
/* remove trailing newline (or carriage return) */
while (len && (ln[len-1] == '\n' || ln[len-1] == '\r'))
ln[--len] = 0;
/* allocate & copy ln saving pointer in t[i], increment i by 1 */
(*t)[idx++] = strdup (ln); /* strdup allocates & copies */
if (idx == maxl) { /* check if you reached limit, realloc if needed */
void *tmp = realloc (*t, maxl * sizeof **t * 2);
if (!tmp) {
fprintf (stderr, "%s() virtual memory exhausted.\n", __func__);
return NULL;
}
*t = tmp; /* set new pointers NULL below (sentinel) */
memset (*t + maxl, 0, maxl * sizeof **t);
maxl *= 2;
}
}
*sz = idx; /* update value at address of sz so it is available in main */
if (fp != stdin) fclose (fp);
return *t;
}
/* format 'n' lines of output of 't' justified as specified in 'just'
(left 'l', right 'r' or centered 'c') within a width 'w'.
NOTE: 'w' must be larger than the longest line in 't'.
*/
void formatted (char **t, char just, size_t w, size_t n)
{
if (!t || !*t) return;
size_t i = 0;
size_t lmax = 0;
size_t len[n];
/* calculate the length of each line, set lmax */
for (i = 0; i < n; i++) {
len[i] = strlen (t[i]);
if (len[i] > lmax) lmax = len[i];
}
/* handle w < lmax reformat or error here */
if (w < lmax) {
fprintf (stderr, "%s() error: invalid width < lmax (%zu).\n",
__func__, lmax);
return;
}
/* left justified output */
if (just == 'l') {
for (i = 0; i < n; i++) {
printf ("%s\n", t[i]);
}
return;
}
/* center or right justified output */
for (i = 0; i < n; i++) {
int spaces = w - len[i];
if (just == 'c')
printf ("%*s%s\n", spaces/2, " ", t[i]);
else if (just == 'r')
printf ("%*s%s\n", spaces, " ", t[i]);
}
}
/* help functions below for calloc, free, and to lower-case */
void *xcalloc (size_t n, size_t s)
{
register void *memptr = calloc (n, s);
if (memptr == 0) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n",
__func__);
exit (EXIT_FAILURE);
}
return memptr;
}
void freecdp (char **p, size_t n)
{
if (!p) return;
size_t i;
for (i = 0; i < n; i++)
free (p[i]);
free (p);
}
unsigned chr2lower (unsigned c)
{ return ('A' <= c && c <= 'Z') ? c | 32 : c; }
$ ./bin/str_justify l 15 dat/fox_4lines.txt
The quick brown
fox jumps over
a lazy
dog.
$ ./bin/str_justify c 15 dat/fox_4lines.txt
The quick brown
fox jumps over
a lazy
dog.
$ ./bin/str_justify r 15 dat/fox_4lines.txt
The quick brown
fox jumps over
a lazy
dog.
关于c - 根据输入来格式化文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33131934/
我有一个简单的 pyparsing 构造,用于提取日志消息的部分内容。看起来像这样 log_line = 时间戳 + task_info + Suppress(LineEnd()) 此结构可以很好地解
我想定义一个函数 scaryDict(),它接受一个参数(textfile)并返回 textfile 中的单词按字母顺序排列,基本上生成字典但不打印任何一个或两个字母的单词。 这是我目前所拥有的……不
我正在尝试弄清楚如何包含对外部数据文件(文本形式)的引用,我希望通过 Web Start (JNLP) 与我的应用程序一起分发该文件。筛选 JNLP 结构的文档,我发现您可以包含对 JAR、nativ
我尝试将 Java 程序从 Eclipse 导出到 .jar 文件,但遇到了问题。它运行良好,但由于某种原因它没有找到它应该从中获取数据的文本文件。如果有人能帮忙解决这个问题,我将非常感激。 最佳答案
在过去的 20 个小时里,我试图解决以下问题,所以在开始考虑跳出窗外之前我想,我最好在这里寻求帮助: I have a text file with following content: ID 1 T
今天我试图删除一个简单文本文件中的重复行,例如: input (list.txt): hello hello try output (list.txt): try 我尝试使用 Notepad++ 删除
我将一个文本文件添加到我的项目中,如下路径所示: Myproject/WebPages/stopwords.txt 图片: http://s7.postimg.org/w65vc3lx7/Untitl
所以我在我的程序上工作,现在我无法找到解决方案。我需要在 fext 文件中替换更多的符号,目前程序只将“TIT”替换为代码“*245$a”,如果我想用同样的方式替换其他字母,程序不会改变。有人知道如何
这是一个非常简单的问题,但无论我看哪里,我都会得到不同的答案(这是因为它在 c++0x 中已经改变还是将要改变?): 在 C++ 中,我如何从一个文本文件中读取两个数字并将它们输出到另一个文本文件中?
我有一个 C++ 项目应该添加 到每一行的开头和到每一行的末尾。这适用于普通英文文本,但我有一个中文文本文件,我想这样做,但它不起作用。我通常使用 .txt 文件,但为此我必须使用 .rtf 来保存中
所以我的驱动看起来像这样: #include "problem2.h" #include "problem1.h" #include "problem3.h" #include #include
我有一个包含字符串标识符的 ascii 数字文本文件(>50k 行),可以将其视为数据 vector 的集合。根据用户输入,应用程序在运行时只需要这些数据 vector 之一。 据我所知,我有 3 个
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: Any decent text diff/merge engine for .NET ? 我有两个文本文件,
我正在尝试将对话选择器中的唤醒时间和 sleep 时间记录到这样的文本文件中,但是对方法 commitToFile2 的调用不会 append 文本文件“savedData.txt”。 我知道这段代码
我开发了一个 android webview 并尝试在单击 webview 中的链接时下载生成的数据:文本文件。 webView.setDownloadListener(new Downloa
我在一个文本文件中有 250 张图像/天 4000*3000 像素。 file '/home/user/camdata/nonseqdata.jpg' file '/home/user/camdata
我曾多次尝试将此配置文件转换为多维数组,这意味着我必须读取 config.txt 文件,然后必须将其转换为多维数组。我需要帮助或一些建议。 配置文件: id=www session.timeout=1
我正在尝试使用 sublime text 3 打开文件,我想用光标在具体行号处打开它。 我一直在查subl --help但我找不到混凝土线的选择。因此我只是使用:subl filename 有没有办法
我想在我的应用程序中快速显示一个大文本文件的内容,而不是将整个文件加载到内存中。 其他人是怎么做的? Total Commander是一个很棒的工具,它有一个很棒的内部查看器可以做到这一点。无论文件有
我是一名优秀的程序员,十分优秀!